Index · Правила · Поиск· Группы · Регистрация · Личные сообщения· Вход

Список разделов Компьютерный раздел
 
 
 

Раздел: Компьютерный раздел Программирование приложений на android 

Создана: 31 Октября 2011 Пон 13:25:33.
Раздел: "Компьютерный раздел"
Сообщений в теме: 223, просмотров: 34607

На страницу: Назад  1, 2,
, 4 ... 13, 14, 15  Вперёд
  1. 31 Октября 2011 Пон 13:25:33
    Набираю желающих в кружок
  2. Foror


    Активист


    Более 10 лет на форумеМуж.
    14 Ноября 2011 Пон 8:42:57
    Присоединяюсь, знаю java, наблюдаю. Если есть желание сделать что-то более жизнеспособное, например "библиотеку в кармане", напишите мне.
  3. 14 Ноября 2011 Пон 9:19:05
    Ага. Присоединил

    А Вы свои идеи опишите в общих словах, а мы обсудим
  4. 14 Ноября 2011 Пон 17:23:06
    Ввод данных (касание экрана и нажатие на клавишу) это системные события.

    Приложение может обратится к системе и получить код события. Затем обработать его с помощью переключателя и таким образом отреагировать на полученную информацию

    Обрабатываем события от touchpad и keypad

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

    Код:
    // Draw the selection...
    Paint selected =   new   Paint();
    selected.setColor(getResources().getColor(
    R.color.puzzle_selected));
    canvas.drawRect(selRect, selected);



    Прямоугольник для курсора вычисляем в самом начале в методе onSizeChanged(), прямоугольник будем рисовать полупрозрачным цветом поверх выбранной ячейки.

    Перемещение курсора при нажатии клавиш управления курсором выполняем с помощью метода onKeyDown( ):
    Внутри метода select( ), мы высчитываем новую координату x и y для курсора и после этого используем метод getRect() для вычисления нового курсора:

    Код:
       private void select(int x, int y) {
          invalidate(selRect);
          selX = Math.min(Math.max(x, 0), 8);
          selY = Math.min(Math.max(y, 0), 8);
          getRect(selX, selY, selRect);
          invalidate(selRect);
       }




    Рисунок. Перемещение курсора


    Тут два обращения к методу invalidate(). Первое сообщает Android о необходимости перерисовывания места старого прямоугольника (на левой стороне рисунка). Второе обращение к invalidate() необходимо для перерисовки нового положения курсора.

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

    При нажатии на цифровую клавишу вызывается метод setTileIfValid. Сначала проверяем введенное значение на предмет его отсутствия в списке использованных значений. Если проверка пройдена то записываем значение в массив puzzle[] с помощью метода setTile и выполняем пересчет значений элементов массивов used и used_hs
  5. 15 Ноября 2011 Втр 12:06:28
    Фиксируем наши идеи относительно ввода данных в коде

    В класс Ira (активити) добавляем три метода

    Код:
    // 3. Ввод данных
          
          // Записываем значение в ячейку если оно не противоречит Судоку
          protected boolean setTileIfValid(int   x,   int   y,   int   value){
             int   tiles[] = getUsedTiles(x, y);
             // Метод getUsedTilesErbol возвращает массив занятых значений
             // для ячейки с координатами x и y
             if   (value != 0) {
                for   (int   tile : tiles) {
                   if   (tile == value)
                      return false;
                }
             }
             // Записываем введенное пользователем значение в элемент массива puzzle
             setTile(x, y, value);
             // Пересчитываем все элементы массива 
             calculateUsedTiles();
             return true;
          }
          
          // Записываем введенное пользователем значение в элемент массива puzzle
          private void setTile(int x, int y, int value) {
             puzzle[y * 9 + x] = value;
          }
          
           /** Создать keypad если сущесвует несколько правильных вариантов */
           public void showKeypadOrError(int x, int y) {
              int tiles[] = getUsedTiles(x, y);
              if (tiles.length == 9) {
                 Toast toast = Toast.makeText(this,R.string.no_moves_label,Toast.LENGTH_SHORT);
                 toast.setGravity(Gravity.CENTER, 0, 0);
                 toast.show();
              } else {
                 Dialog v = new Keypad(this, tiles, iraView);
                 v.show();
              }
           }
          


    В методе showKeypadOrError проверяем сначала наличие не занятых цифр для активной ячейки. Если их нет , то выводим сообщение (оповещение) - типа мест нет. Это делается с помощью объекта Toast.

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

    Выбранная с помощью диалога цифра помещается в ячейку.

    Сам диалог может быть оформлен как решетка из девяти или менее элементов (типа кнопок) в зависимости от ситуации для текущей ячейки

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

    Реализация поставленной задачи происходит следующим образом. Сначала с помощью инструкций XML определяем геометрию и положение на экране решетки из девяти одинаковых прямоугольников (кнопки с изображением цифр на них). Потом в классе keypad создаем для каждой из кнопок "слушателя", который реагирует на касание экрана в области заданной с помощью макета.

    В класс IraView добавляем методы которые реагируют на ввод и рисуют изменения в ячейках Судоку

    Код:
    // 2. Ввод данных   
       
          @Override
          public boolean onTouchEvent(MotionEvent event) {
             if (event.getAction() != MotionEvent.ACTION_DOWN)
                return super.onTouchEvent(event);

             select((int) (event.getX() / width),
                   (int) (event.getY() / height));
             ira.showKeypadOrError(selX, selY);
             return true;
          }
          
          @Override
          public boolean onKeyDown(int keyCode, KeyEvent event) {
             switch (keyCode) {
             case KeyEvent.KEYCODE_DPAD_UP:
                select(selX, selY - 1);
                break;
             case KeyEvent.KEYCODE_DPAD_DOWN:
                select(selX, selY + 1);
                break;
             case KeyEvent.KEYCODE_DPAD_LEFT:
                select(selX - 1, selY);
                break;
             case KeyEvent.KEYCODE_DPAD_RIGHT:
                select(selX + 1, selY);
                break;
             case KeyEvent.KEYCODE_0:
             case KeyEvent.KEYCODE_SPACE: setSelectedTile(0); break;
             case KeyEvent.KEYCODE_1:     setSelectedTile(1); break;
             case KeyEvent.KEYCODE_2:     setSelectedTile(2); break;
             case KeyEvent.KEYCODE_3:     setSelectedTile(3); break;
             case KeyEvent.KEYCODE_4:     setSelectedTile(4); break;
             case KeyEvent.KEYCODE_5:     setSelectedTile(5); break;
             case KeyEvent.KEYCODE_6:     setSelectedTile(6); break;
             case KeyEvent.KEYCODE_7:     setSelectedTile(7); break;
             case KeyEvent.KEYCODE_8:     setSelectedTile(8); break;
             case KeyEvent.KEYCODE_9:     setSelectedTile(9); break;
             case KeyEvent.KEYCODE_ENTER:
             case KeyEvent.KEYCODE_DPAD_CENTER:
                ira.showKeypadOrError(selX, selY);
                break;
             default:
                return super.onKeyDown(keyCode, event);
             }
             return true;
          }
          
    //      Внутри метода select( ), мы высчитываем новую координату x и y
    //      для курсора и после этого используем метод getRect()
    //      для вычисления нового курсора:
          private void select(int x, int y) {
             invalidate(selRect);
             selX = Math.min(Math.max(x, 0), 8);
             selY = Math.min(Math.max(y, 0), 8);
             getRect(selX, selY, selRect);
             invalidate(selRect);
          }
          
          public void setSelectedTile(int tile) {
                if (ira.setTileIfValid(selX, selY, tile)) {
                   invalidate();// may change hints
                } else {
                   // Number is not valid for this tile
                }
          }
          


    А это класс Keypad который осуществляет прослушивание кнопок в окне диалога и передачу выбранного значения методу setSelectedTile(tile) класса IraView

    Код:
    package com.ira;

    import android.app.Dialog;
    import android.content.Context;
    import android.os.Bundle;
    import android.view.KeyEvent;
    import android.view.View;

    public class Keypad extends Dialog {

       protected static final String TAG = "Sudoku";

       private final View keys[] = new View[9];
       private View keypad;

       private final int useds[];
       private final IraView iraView;

       public Keypad(Context context, int useds[], IraView iraView) {
          super(context);
          this.useds = useds;
          this.iraView = iraView;
       }

       @Override
       protected void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);

          setTitle(R.string.keypad_title);
          setContentView(R.layout.keypad);
          findViews();
          for (int element : useds) {
             if (element != 0)
                keys[element - 1].setVisibility(View.INVISIBLE);
          }
          setListeners();
         
       }

       @Override
       public boolean onKeyDown(int keyCode, KeyEvent event) {
          int tile = 0;
          switch (keyCode) {
          case KeyEvent.KEYCODE_0:
          case KeyEvent.KEYCODE_SPACE: tile = 0; break;
          case KeyEvent.KEYCODE_1:     tile = 1; break;
          case KeyEvent.KEYCODE_2:     tile = 2; break;
          case KeyEvent.KEYCODE_3:     tile = 3; break;
          case KeyEvent.KEYCODE_4:     tile = 4; break;
          case KeyEvent.KEYCODE_5:     tile = 5; break;
          case KeyEvent.KEYCODE_6:     tile = 6; break;
          case KeyEvent.KEYCODE_7:     tile = 7; break;
          case KeyEvent.KEYCODE_8:     tile = 8; break;
          case KeyEvent.KEYCODE_9:     tile = 9; break;
          default:
             return super.onKeyDown(keyCode, event);
          }
          if (isValid(tile)) {
             returnResult(tile);
          }
          return true;

       }

       /** Return the chosen tile to the caller */
       private void returnResult(int tile) {
          // возвращаем выбранное значение
          iraView.setSelectedTile(tile);
          // выход из диалога
          dismiss();
       }

       private boolean isValid(int tile) {
          for (int t : useds) {
             if (tile == t)
                return false;
          }
          return true;
       }

       private void findViews() {
          keypad = findViewById(R.id.keypad);
          keys[0] = findViewById(R.id.keypad_1);
          keys[1] = findViewById(R.id.keypad_2);
          keys[2] = findViewById(R.id.keypad_3);
          keys[3] = findViewById(R.id.keypad_4);
          keys[4] = findViewById(R.id.keypad_5);
          keys[5] = findViewById(R.id.keypad_6);
          keys[6] = findViewById(R.id.keypad_7);
          keys[7] = findViewById(R.id.keypad_8);
          keys[8] = findViewById(R.id.keypad_9);
       }
    //
       private void setListeners() {
          for (int i = 0; i < keys.length; i++) {
             final int t = i + 1;
             keys[i].setOnClickListener(new View.OnClickListener(){
                public void onClick(View v) {
                   returnResult(t);
                }});
          }
         
          keypad.setOnClickListener(new View.OnClickListener(){
             public void onClick(View v) {
                returnResult(0);
             }});
       }
    }
  6. 17 Ноября 2011 Чтв 14:37:16
    Интересно как все это будет работать. Пока что нам не хватает макета клавиатуры в окне диалога , текста сообщения которое выводится с помощью Оповещения (Toast) в том случае если список возможных значений для ячейки заполнен полностью (все девять значений заняты)


    Теория

    Все ресурсы создаются и сохраняются в предопределенных подкаталогах в каталоге res/ nроекта
    res/anim/ - файлы анимации.
    res/drawaЬle/ - графика.
    res/layout/ - ХМL-файлы для схем разметки .
    res/values/ - ХМL-файлы , которые могут быть откомпилированы во многие виды ресурса. В отличие от других каталогов, res/ может содержать любое число файлов. При создании файлов ресурсов следует соблюдать соглашение об именовании файлов ресурсов по типу элементов, определенных в них:
    • arrays .xml - массивы ;
    • colors.xml - значения цвета для графики и строк текста;
    • dimens.xml - размерности ;
    • strings.xml - строковые значения;
    • styles.xml - стили .
    res/xml/ - произвольные ХМL-файлы , которые могут загружаться во время выполнения.
    res/raw/ - произвольные файлы , предназначенные для копирования непосредственно
    на устройство.

    Значение атрибута ХМL-элемента (или ресурса) может также быть ссылкой на ресурс.

    Например, если мы имеем цветовые ресурсы , мы можем записать файл разметки, который устанавливает значение цвета для текста, находящегося в одном из этих ресурсов :

    android : textColor= "@color/opaque_red"

    Обратите внимание здесь на использование префикса @ для того, чтобы ввести ссылку ресурса - текст после этого префикса - имя ресурса. В этом случае мы не должны были указывать пакет, потому что мы ссылаемся на ресурс в нашем собственном пакете. Для ссылки на системный ресурс мы должны записать :

    android : textColor= "@android : color/opaque_red"


    Класс R имеет несколько вложенных классов, один для каждого типа ресурса, поддерживаемого системой Android, и для которого в проекте существует файл ресурса.
    Класс R может содержать следующие вложенные классы :

    R.anim - идентификаторы для файлов из каталога res/an i m/;
    R.array - идентификаторы для файлов из каталога res/values/;
    R.bool - идентификаторы для битовых массивов в файлах arrays.xml из каталога res/values/;
    R.color - идентификаторы для файлов colors.xm l из каталога res/values/;
    R.dimen - идентификаторы для файлов dimens.xml из каталога res/values/;
    R.drawable - идентификаторы для файлов из каталога res/drawable/;
    R.id - идентификаторы представлений и групп представлений для файлов ХМL-разметки из каталога res/layout/;
    R.integer - идентификаторы для целочисленных массивов в файлах arrays.xml из каталога res/values/;
    R.layout - идентификаторы для файлов разметки из каталога res/layout/;
    R.raw - идентификаторы для файлов из каталога res/raw/;
    R.string - идентификаторы для файлов strings.xml из каталога res/values/;
    R.style - идентификаторы для файлов styles.xml из каталога res/values/;
    R.xml - идентификаторы для файлов из каталога res/xml/.

    Каждый вложенный класс содержит один или несколько идентификаторов для откомпилированных ресурсов, которые используются в коде программы для загрузки ресурса.

    arrays.xml - для массивов строк или целочисленных значений ;
    colors.xml - для значений цвета;
    dimen .xml - для значений размеров текста;
    drawables.xml - для графических примитивов.


    Файлы меню сохраняются в отдельном каталоге res/menu/.

    В ХМL-файле меню есть три элемента:
    <menu> - корневой элемент файла меню;
    <group> - контейнерный элемент, определяющий группу меню;
    <item> - элемент, определяющий пункт меню.

    Элементы < itern> и <group> могут быть дочерними элементами <group>. Корневой узел любого файла должен быть элементом меню.

    Подробнее ознакомится с использованием ресурсов можно в книге Голощапова «Google Android программирование для мобильных устройств»


    Наши действия

    Вставляем в файл strings.xml определение для ресурса no_moves_label

    Вот так будет выглядеть файл strings.xml. Он расположен в папке values

    Код:
    <?xml version="1.0" encoding="utf-8"?>
    <resources>
       <string name="app_name">Судоку</string>
       <string name="no_moves_label">Нет вариантов</string>
       <string name="keypad_title">Клавиатура</string>
    </resources>



    Это файл keypad.xml. Надо его создать в папке layout

    Код:
    <?xml version="1.0" encoding="utf-8"?>
    <TableLayout
       xmlns:android="http://schemas.android.com/apk/res/android"
       android:id="@+id/keypad"
       android:orientation="horizontal"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:gravity="right"
       android:stretchColumns="*">
       <TableRow>
          <Button android:id="@+id/keypad_1"
             android:textSize="30sp"
             android:text="1">
          </Button>
          <Button android:id="@+id/keypad_2"
             android:textSize="30sp"
             android:text="2">
          </Button>
          <Button android:id="@+id/keypad_3"
             android:textSize="30sp"
             android:text="3">
          </Button>
       </TableRow>
       <TableRow>
          <Button android:id="@+id/keypad_4"
             android:textSize="30sp"
             android:text="4">
          </Button>
          <Button android:id="@+id/keypad_5"
             android:textSize="30sp"
             android:text="5">
          </Button>
          <Button android:id="@+id/keypad_6"
             android:textSize="30sp"
             android:text="6">
          </Button>
       </TableRow>
       <TableRow>
          <Button android:id="@+id/keypad_7"
             android:textSize="30sp"
             android:text="7">
          </Button>
          <Button android:id="@+id/keypad_8"
             android:textSize="30sp"
             android:text="8">
          </Button>
          <Button android:id="@+id/keypad_9"
             android:textSize="30sp"
             android:text="9">
          </Button>
       </TableRow>
    </TableLayout>



    Это main.xml (папка layout)

    Код:
    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:orientation="vertical"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        >
    <TextView 
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        />
    </LinearLayout>


    Запускаем, смотрим.
  7. 22 Ноября 2011 Втр 23:00:23
    Как результат наших действий игра взаимодействует с игроком. Данные можно вводить с клавиатуры и касанием ячейки на экране.

    Я сам не игрок, но мне кажется что с позиции игрока важным свойством является возможность настройки. В нашем случае можно музыку включать/выключать , показывать/скрывать цвет ячеек найденных с помощью логики используемых методов. Также можно вводить новые начальные условия для Судоку, то есть расстановку цифр в начале игры

    Таким образом получается что мы буде использовать два checkbox и одно поле TextEdit. Checbox`ы будем использовать для выбора проигрывать музыку или нет во время игры и показывать или не показывать подсказки. TextEdit для ввода строки из 81 цифры, в которой номер элемента строки это номер ячейки Судоку, а значение элемента строки это значение которое надо поместить в эту ячейку.

    Создаем макет экрана с установками. Записываем все это в файл settings.xml. Говорят что в папке Layout этот файл себя ведет не понятно, поэтому создаем папку xml и и помещаем его туда.

    Код:
    <?xml version="1.0" encoding="utf-8"?>
    <PreferenceScreen
       xmlns:android="http://schemas.android.com/apk/res/android">

       <CheckBoxPreference
          android:key="Музыка"
          android:title="@string/music_title"
          android:summary="@string/music_summary"
          android:defaultValue="true" />
       <CheckBoxPreference
          android:key="Подсказки"
          android:title="@string/hints_title"
          android:summary="@string/hints_summary"
          android:defaultValue="true" />
         
                <EditTextPreference
             android:key="Судоку"
             android:title="Комбинация Судоку"
             android:summary="Ряд за рядом"
             android:textSize="30sp"
             android:defaultValue="046050107030400905000001000500000010004907500020000008000300000103005070408
    070320"
             android:dialogTitle="Введите комбинацию цифр Судоку" />
    </PreferenceScreen>


    Еще надо дополнить файл strings.xml в папке val

    Код:
    <?xml version="1.0" encoding="utf-8"?>
    <resources>
       <string name="app_name">Судоку</string>
       <string name="no_moves_label">Нет вариантов</string>
       <string name="keypad_title">Клавиатура</string>
       
       <string name="settings_label">Установки...</string>
       <string name="settings_title">Установки Судоку</string>
       <string name="settings_shortcut">s</string>
       <string name="music_title">Музыка</string>
       <string name="music_summary">Играть музыку в фоне</string>
       <string name="hints_title">Подсказки</string>
       <string name="hints_summary">Показывать подсказки в продолжении игры</string>
    </resources>


    Создаем класс Prefs.java

    Код:
    import android.content.Context;
    import android.os.Bundle;
    import android.preference.PreferenceActivity;
    import android.preference.PreferenceManager;

    public class Prefs extends PreferenceActivity {
       // Option names and default values
       private static final String OPT_MUSIC = "Музыка";
       private static final boolean OPT_MUSIC_DEF = true;
       private static final String OPT_HINTS = "Подсказки";
       private static final boolean OPT_HINTS_DEF = true;
       private static final String OPT_S = "Судоку";
       private static final String OPT_S_DEF = "";
       

       @Override
       protected void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
          addPreferencesFromResource(R.xml.settings);
       }

       
       /** Get the current value of the music option */
       public static boolean getMusic(Context context) {
          return PreferenceManager.getDefaultSharedPreferences(context)
                .getBoolean(OPT_MUSIC, OPT_MUSIC_DEF);
       }
       
       /** Get the current value of the hints option */
       public static boolean getHints(Context context) {
          return PreferenceManager.getDefaultSharedPreferences(context)
                .getBoolean(OPT_HINTS, OPT_HINTS_DEF);
       }
       
       /** Get the current value of the music option */
       public static String getSudoku(Context context) {
          return PreferenceManager.getDefaultSharedPreferences(context)
                .getString(OPT_S, OPT_S_DEF);
       }
       
    }



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

    • getBoolean(String key, boolean defValue);
    • getFloat(String key, float defValue);
    • getInt(String key, int defValue);
    • getLong(String key, long defValue);
    • getString(String key, String defValue)

    для получения нужной настройки

    Теперь надо эти настройки использовать для выбора нужного действия

    В класс Ira добавляем два метода

    Код:
        @Override
        protected void onResume() {
           super.onResume();
           Music.play(this, R.raw.africa);
        }

       
        @Override
        protected void onPause() {
           super.onPause();
           Music.stop(this);
        }



    В папке res создаем новую папку raw и вставляем туда файл в формате mp3. Я назвал песню africa.mp3

    Запускаем смотрим

    Извиняюсь, наврал

    Надо еще один класс создать, который умеет музыку проигрывать

    Код:
    package com.ira;

    import android.content.Context;
    import android.media.MediaPlayer;


    public class Music {
       private static MediaPlayer mp = null;

       
       /** Stop old song and start new one */
       public static void play(Context context, int resource) {
          stop(context);

          // Start music only if not disabled in preferences
          if (Prefs.getMusic(context)) {
             mp = MediaPlayer.create(context,  resource);
             mp.setLooping(true);
             mp.start();
          }

       }
       

       /** Stop the music */
       public static void stop(Context context) {
          if (mp != null) {
             mp.stop();
             mp.release();
             mp = null;
          }
       }
    }


    Кроме того надо еще создать макет меню. И поместить его в папку res/menu

    Код:
    <?xml version="1.0" encoding="utf-8"?>

    <menu xmlns:android="http://schemas.android.com/apk/res/android">
       <item android:id="@+id/settings"
          android:title="@string/settings_label"
          android:alphabeticShortcut="@string/settings_shortcut" />
    </menu>


    Еще раз извиняюсь. В класс Ira.java добавляем методы для активации меню и пакеты соответствующие

    Код:
        @Override
        public boolean onCreateOptionsMenu(Menu menu) {
            super.onCreateOptionsMenu(menu);
            MenuInflater inflater = getMenuInflater();
            inflater.inflate(R.menu.menu, menu);
            return true;
         }

         @Override
         public boolean onOptionsItemSelected(MenuItem item) {
            switch (item.getItemId()) {
            case R.id.settings:
               startActivity(new Intent(this, Prefs.class));
               return true;
            // More items go here (if any) ...
            }
            return false;
         }


    Вот пакеты которые нужно импортировать в класс

    import android.view.Menu;
    import android.view.MenuInflater;
    import android.view.MenuItem;

    На экране приложения должен появиться значок Настроек - прямоугольник заполненный горизонтальными линиями

    Для изменения настроек щелкаем на этот значок
  8. 23 Ноября 2011 Срд 13:06:45
    Проблема такая нарисовалась. При запуске приложения на эмуляторе получаем сообщение в консоли eclipse

    INSTALL_FAILED_INSUFFICIENT_STORAGE

    Решение
    Идём в Run configurations, там проставляем дефолтный эмулятор, который надо запускать, идём сюда: "additional emulator command line options" и прописываем

    -partition-size 1024

    Если на данный момент запущен какой-то эмулятор типа AVD, то убить.

    [внешняя ссылка]
  9. 24 Ноября 2011 Чтв 23:24:37
    Из трех Настроек - музыка, подсказка и Расклад мы сейчас используем только музыку.

    Чтобы подключить Расклад, то есть начальную комбинацию цифр в ячейках Судоку сделаем так, Добавим в метод onCreate класса Ira код

    if (Prefs.getSudoku(this).length()==81) {
    Log.d("Sudoku", "value :" + Prefs.getSudoku(this));
    puz = Prefs.getSudoku(this);
    };

    Тогда получим

    Код:
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
           
          if (Prefs.getSudoku(this).length()==81) {
             Log.d("Sudoku",   "value :" +  Prefs.getSudoku(this));
             puz = Prefs.getSudoku(this);
          };
           
            // Инициализация массива puzzle
          puzzle = getPuzzle(puz);
          // Инициализация массивов used и used_hs
          calculateUsedTiles();
          
          iraView =   new   IraView(this);
          setContentView(iraView);
          iraView.requestFocus();
        }


    Еще надо убрать модификатор static из объявления puz. Будет так

    private String puz = "046050107030400905000001000500000010004907500020000008000300000103005070408
    070320";

    У метода getSudoku аргумент имеет тип Context. Activity является подклассом Context, поэтому мы можем использовать ее – this.

    [внешняя ссылка]
  10. 26 Ноября 2011 Суб 10:50:55
    Последняя настройка это "Подсказка". То есть если мы хотим раскрасить ячейки Судоку в цвета в соответствии с количеством вариантов заполнения то выбираем в Настройках флажок "Подсказка".

    Чтобы эта настройка действовала на код надо в методе onDraw использовать условный оператор который будет отслеживать состояние флага

    if (Prefs.getHints(getContext())) {
    }


    Код:
       if (Prefs.getHints(getContext())) {

            // Draw the hints...
            // Pick a hint color based on #moves left
            Paint hint = new Paint();
            int c[] = { getResources().getColor(R.color.puzzle_hint_0),
                  getResources().getColor(R.color.puzzle_hint_1),
                  getResources().getColor(R.color.puzzle_hint_2), };
            Rect r = new Rect();
            for (int i = 0; i < 9; i++) {
               for (int j = 0; j < 9; j++) {
                  int movesleft = 9 - ira.getUsedTiles(i, j).length;
                  if (movesleft < c.length) {
                     getRect(i, j, r);
                     hint.setColor(c[movesleft]);
                     canvas.drawRect(r, hint);
                  }
               }
            }
           }
  11. 29 Ноября 2011 Втр 22:24:20
    Чтобы иметь возможность работы с кэшем объекта view надо определить его идентификатор. Кэш нам нужен для того чтобы сохранить в нем позицию курсора, то есть номер активной ячейки и текущий расклад цифр по ячейкам Судоку.

    Эти данные запоминаются при повороте планшета. Наступление и обработку события поворот планшета фиксируем с помощью метода onSaveInstanceState(). Надо переписать его. Инициализацию объекта View, в частности обращение к кэшу за данными., после поворота обрабатываем с помощью метода onRestoreInstanceState

    Вставляем в конец конструктора класса IraView инструкцию

    setId(1);

    Теперь можем пользоваться кэшем

    Вставляем в класс IraView два метода которые сохраняют данные в кэше и восстанавливают таблицу Судоку по данным хранящимся в кэше

    Код:
       // Сохраняем положение курсора в хеше, то есть активной ячейки
       // при перевороте планшета
          @Override
          protected Parcelable onSaveInstanceState() {
             Parcelable p = super.onSaveInstanceState();

             Bundle bundle = new Bundle();
             bundle.putInt("selX", selX);
             bundle.putInt("selY", selY);
             String s0 = toPuzzleStringErbol(puzzle);
             bundle.putString("s0", s0);
             bundle.putParcelable("viewState", p);
             return bundle;
          }
          @Override
          
          // Забираем из хеша сохраненные данные о координатах
          // активной ячейки
          protected void onRestoreInstanceState(Parcelable state) {

             Bundle bundle = (Bundle) state;
             selectErbol(bundle.getInt("selX"), bundle.getInt("selY"));
             String s0 = bundle.getString("s0");
             puzzle = getPuzzleErbol(s0);
             calculateUsedTilesErbol();
             Log.d("Value",s0);
             super.onRestoreInstanceState(bundle.getParcelable("viewState"));
             return;
          }


    Запускаем смотрим. Для того чтобы поменять ориентацию экрана симулятора можно использовать комбинацию Ctrl + F11
  12. 02 Декабря 2011 Птн 10:08:21
    С Судоку закончили. Но тут на подходе библиотека AndEngine которая позволяет двухмерные игры создавать.

    Хочу разобрать статью "Пишем игру для Android c помощью AndEngine".

    [внешняя ссылка]

    Ваши предложения, замечания ?
  13. 02 Декабря 2011 Птн 12:28:12
    Постановка: Рисуем игрушку "Лазеры и зеркала" наподобие "Mirrors Maze"

    [внешняя ссылка]

    В данном случае действующими лицами будут рисунки лазера , зеркал и фона (background)

    Классы библиотеки AndEngine

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

    Camera - отвечает за то, что вы увидите на экране. Всё, что за пределами камеры, на экране не видно. Размер Camera обычно устанавливается равным размеру экрана устройства.

    Подклассы Camera:
    1. BoundCamera — перемещается по сцене в заданных рамках;
    2. ZoomCamera — камера с произвольным увеличением сцены. Расширяет класс BoundCamera;
    3. SmoothCamera — расширяет ZoomCamera. Производит плавное увеличение/уменьшение зума при его изменении;

    Camera может следовать за каким-нибудь объектом


    Scene является контейнером для объектов — других сцен, спрайтов, графических примитивов.
    При создании игры обязательно нужно создать хотя бы одну Scene, в методе onLoadScene


    Entity (Сущность) Entity содержит методы по изменению цвета, масштабированию, повороту, видимости и прочие.
    Entity можно использовать, например, как простой контейнер для спрайтов добавлять к основной Scene (типа слой).

    Modifiers (Модификаторы). Вот какие модификаторы предоставлет AndEngine:

    1. Меняющие прозрачность;
    2. Меняющие цвет;
    3. Меняющие положение (x и y), в том числе изменение по заданным точкам (пути);
    4. Меняющие угол (вращение спрайта);
    5. Меняющие масштаб;

    Основные методы класса BaseGameActivity

    onLoadEngine
    onLoadResources
    onLoadScene
    onLoadComplete

    [внешняя ссылка]

    Сама статья состоит из 4 частей. Во второй части автор создает несколько типов данных определяя их через класс Entity.

    В начале было отмечено что в игре участвуют разные объекты. Сообразно их поведению определяем методы и свойства для создаваемых типов данных (классов)
  14. 07 Декабря 2011 Срд 9:26:21
    Главное в игре Mirrors Maze это отрисовка пути лазера по точкам. Первая совпадает с пушкой, далее добавляем точки при выходе за экран, остановке и отражении

    Если угол движения известен, то найти следующую точку не сложно

    Автор предлагает такую схему

    Код:
    private void nextPosition(Point position, final int angle) {
          switch (angle) {
          case DynamicGameObject.DEG_0:
             position.x++;
             break;
          case DynamicGameObject.DEG_90:
             position.y++;
             break;
          case DynamicGameObject.DEG_180:
             position.x—;
             break;
          case DynamicGameObject.DEG_270:
             position.y—;
             break;
          case DynamicGameObject.DEG_45:
             position.x++;
             position.y++;
             break;
          case DynamicGameObject.DEG_135:
             position.x—;
             position.y++;
             break;
          case DynamicGameObject.DEG_225:
             position.x—;
             position.y—;
             break;
          case DynamicGameObject.DEG_315:
             position.x++;
             position.y—;
             break;
          default:
             break;
          }

       }



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

    Пусть зеркало неподвижно а луч падает на него под разными углами

    1. 0 градусов – нет отражения
    2. 45 – 315
    3. 90 – нет отражения
    4. 135 – 225
    5. 180 – нет отражения
    6. 225 – 135
    7. 270 – нет отражения
    8. 315 – 45
  15. 08 Декабря 2011 Чтв 12:09:40
    Решим задачу определения направления отраженного луча в общем случае когда вращаются и зеркало и лазерная пушка.

    Зеркало двухстороннее. Введем обозначения. Угол между зеркалом (лучом) и осью Y равный 0 градусов обозначим 0
    2. Равный 45 градусам - обозначим 1
    3. 90 градусов - 2
    4. 135 - 3
    5. 180 - 4
    6. 225 - 5
    7. 270 - 6
    8. 315 - 7

    Нужно получить такую формулу чтобы полученное значение угла не превышало число 7.

    Еще обозначения

    b - угол луча с осью Y
    a - угол зеркала с осью Y

    Из предыдущего рассмотрения видно, что между углами выполняются следующие соотношения

    Если b = a + 1, то новое значение b, после отражения будет равно a + 7
    Если b = a + 7, то b`= a + 1
    Если b = a + 3, то b`= a + 5
    Если b = a + 5, то b`= a + 3

    В общем можно все это так записать

    Код:
    @Override
       int onLaser(int angle) {
          int a = getAngle() % 4;
          // Операция - остаток от деления
          if (angle == (a + 1) % 8) return (a + 7) % 8;
          if (angle == (a + 7) % 8) return (a + 1) % 8;
          if (angle == (a + 3) % 8) return (a + 5) % 8;
          if (angle == (a + 5) % 8) return (a + 3) % 8;
          return -1;
       }
  16. 26 Декабря 2011 Пон 19:59:03
    Продолжаем изучать игру "Зеркала и лазеры".

    Для случая когда направление луча меняется более плавно, допустим не с шагом 45 градусов, а с шагом 15 градусов можно вывести общие формулы которые бы определяли угол отраженного луча относительно некоторой оси Y в зависимости от угла падения луча и угла наклона зеркала к оси Y, a и b соответственно

    Для начала нужно определить угол падения луча по отношению к оси зеркала.

    Если a > b , угол луча по отношению к зеркалу , назовем его c , будет равен

    c = a - b

    Если a < b , угол с равен

    c = (a + 360) - b

    После того как определен угол с (угол падения на зеркало) можно вычислить угол отраженного луча.

    c`= 360 - c

    Теперь можно рассчитать угол отраженного луча по отношению к оси Y

    d = c` + b
На страницу: Назад  1, 2,
, 4 ... 13, 14, 15  Вперёд