/>
Sun's site Java Tips

Этот сайт посвящен вопросам программирования на Java. Все, что здесь описано, является результатом моих личных экспериментов %) В основном сведения, помещенные здесь, касаются разработки аплетов и MIDP-приложений (J2ME).

[АПЛЕТЫ] [J2ME] [АЛГОРИТМЫ] [ФОРУМ] [КОНТАКТЫ] [ССЫЛКИ]

АПЛЕТЫ

Пара мелочей

- Когда вы программируете аплет, у вас будет необходимость часто перезапускать ваш аплет в браузере. Иногда аплет "застревает" в кэше и, что бы вы ни делали, загружается старая версия аплета. Чтобы перезапустить аплет без кэша используйте Ctrl+Shift+Обновить.

- В Windows2000 аплеты (а значит и jvm) работают заметно быстрее, чем в Windows9x.

- Все объекты java.awt.Graphics необходимо явно освобождать методом dispose(), так как они могут не освобождать занятые графические контексты автоматически. Лучше всего это делать в методе destroy() аплета. Если этого не делать, то после нескольких запусков вашего аплета Windows не сможет создавать новые графические контексты, а значит и рисовать в окнах.

- Если вы используете потоки (Threads) создавайте и уничтожайте их в методах start() и stop(). Некорректное создание/уничтожение потоков может привести к тому, что после завершения аплета поток останется в памяти. Код должен быть примерно такой:


public void start(){
  if (yourThread==null){
    yourThread=new Thread(this);
    yourThread.start();
  }
}

public void stop(){
  if (yourThread!=null){
    yourThread.stop();
    yourThread=null;
  }
}

- Обычно в методе run() потока присутствует цикл do { ... } while (true); Внутри цикла рекомендуется "усыплять" поток на короткие промежутки, иначе он захватывает почти 100% процессорного времени (особенно актуально для windows9x). Не поленитесь перед }while (true); поставить следующее


try {animator.sleep(10);}
catch(InterruptedException e){};

Синхронизация скорости работы аплета

Аплеты могут работать с различной скоростью на машинах с разными характеристиками. Это может привести например к тому, что в вашу игру не сможет играть человек с P4, так как у него все будет летать слишком быстро. Или наоборот - слишком медленно на P 200 %) Основная причина, влияющая на скорость работы аплета это вывод графики на экран. Это очень важная тема и я о ней обязательно напишу. Есть два способа синхронизации по времени, которые я опробовал.

1. Вы определяете, сколько миллисекунд должно занимать выполнение основного рабочего цикла аплета. Предположим вы хотите, чтобы ваш аплет выдавал 35 кадров в секунду, тогда один цикл должен выполняться за 1000/35 миллисекунд. Затем вы засекаете время перед началом выполнения основного цикла (c помощью System.currentTimeMillis()) и после, вычисляете разницу и делаете необходимую задержку. 

Пример:

final long desiredFPS=35;
final long desiredTime=1000/desiredFPS;
. . .
public void run(){
  long lastTime=System.currentTimeMillis()+desiredTime;
  . . .  // Здесь идет основной цикл аплета, перерисовка экрана и т.п.
  while(System.currentTimeMillis() < lastTime);
}

Этот метод имеет свои недостатки. Во-первых вы можете только понизить скорость работы аплета, но никак не повысить. Во-вторых из-за неточностей округления и неполного соответствия значения функции System.currentTimeMillis() текущему времени, аплет начинает работать заведомо медленнее того, как он может, кроме того вы не можете получить некоторые из значений desiredFPS, а только меньшие.


2. Второй способ заключается в том, что у вас есть некая глобальная переменна - скорость. Она вычисляется в зависимости от того, на сколько скорость выполнения аплета отличается от желаемой. Потом эта переменная используется (каждый раз), когда вы вычисляете скорости объектов, время задержек (если оно не привязано к таймеру) и т.п. Пример:

final long desiredFPS=35;
final long desiredTime=1000/desiredFPS;
final double initSpeed=1;
double speed=initSpeed;
. . .
public void run(){
  long lastTime=System.currentTimeMillis()+desiredTime;
  . . .  // Здесь идет основной цикл аплета, перерисовка экрана и т.п.
  int dTime=System.currentTimeMillis()-lastTime;
  if (dTime!=0){
    speed=initSpeed*dTime/desiredTime;
  }
}
. . .

class MovingObject{
  int x,y;
  int vx,vy;
. . .

  void move(double speed){ // сюда передаете 'скорость аплета'
    x+=vx*speed;
    y+=vy*speed;
  }
};

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

Что лучше? Попробуйте сами %)

Взаимодействие Java-аплета с JavaScript(JS)


Для того, чтобы получить доступ к методам аплета из JS достаточно использовать встроенный массив applets. Например для вызова метода аплета method():

document.applets[0].method();
document.applets["myapplet"].method();

Предполагается, что на странице первый из аплетов объявлен как

<APPLET CODE="some.class" NAME="myapplet" WIDTH=200 HEIGHT=200> </APPLET>

Можно передавать какие-либо данные в аплет в качестве параметров вызываемых методов, но я с этим не экспериментировал, попробуйте сами, если хотите %)

Можно также обращаться из аплета к методам JS. Для этого необходимо использовать пакет netscape.javascript, который вроде бы входит в стандартную поставку JVM для Windows. Если нет, то его можно скачать где-нибудь. В этом пакете определены два класса - JSObject и JSException. Последний - это исключение, которое генерируется в случае каких-либо ошибок работы экземпляра класса JSObject.

Чтобы создать экземпляр класса JSObject необходимо воспользоваться его статическим методом getWindow(Applet ap). То есть

JSObject jsGate=JSObject.getWindow(this);

После этого можно вызывать любые функции JS используя конструкцию

jsGate.eval("jsfunction();");

Можно и параметры передавать. Последний пример демонстрирует вызов функции AcceptByte, объявленной в JS:

JSObject jsGate=JSObject.getWindow(this);
byte b=10;
jsGate.eval("AcceptByte("+b+");");

Я использовал JS для передачи информации между аплетами. Например в JS было что-то вроде

function send(){document.applets[0].acceptObject(document.applets[1].getObject());}

Внимание! Такой способ работает только в Java 1. С Java2 плагином вызов такой функции вызывает крушение браузера.

Звук в аплетах

Java1.x поддерживает воспроизведение только звуков в формате Sun (*.au). При этом звук должен быть 8KHz 8 битный (вроде бы можно и 16 бит) и моно.

- Одна из проблем, общее решение которой я так и не нашел, - загрузка звуков до их первого проигрывания. MediaTracker в Java1.x не поддерживает загрузку звуков. Есть идея загружать звуковой файл как обычный файл побайтно, а потом проигрывать. Предполагается, что файл окажется в кэше. Однако этот способ мне не нравится, даже если он будет работать. Я просто проигрываю критичные звуки еще до начала загрузки изображений.

- Вторая серьезная проблема возникает при проигрывании звука в том случае, когда операционная система не может микшировать звук (т.е. если звуковое устройство (ЗУ) занято, то оно недоступно). Дело в том, что JVM проверяет доступность ЗУ только при первом проигрывании звука, а потом проигрывает звуки без проверки. Тогда если после первого проигрывания какое-то приложение займет ЗУ (например пользователь запустил WinAmp), то при попытке проиграть очередной звук аплет повиснет с выдачей 'No audio device' в консоль. Решение состоит в том, чтобы захватить ЗУ и не освобождать его все время, пока работает аплет. Чтобы сделать это, надо создать короткий по времени файл с тишиной и после загрузки аплета проигрыват его методом AudioClip.loop() и останавливать только перед выгрузкой аплета из памяти (AudioClip.stop()). Надо заметить, что поток Audio Player, который проигрывает звуки в JVM, микширует au-файлы без всяких проблем (ну почти).

- Для обработки звуковых файлов я пользуюсь Cool Edit Pro.

 

J2ME

Введение

 Сегодня приложения под эту платформу становятся все более популярными. Дело в том, что практически все современные модели телефонов поддерживают J2ME. Сейчас основной тип приложения для J2ME это игры. Приложения для J2ME (мидлеты) позиционируются как кроссплатформенные, но на практике это не совсем так.

Проблемы:

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

  • Есть цветные и ч/б экраны. Тут уж графику переделать придется точно.

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

  • Разная раскладка клавиатуры (см. например Nokia 3650). Это решается стандартными средствами J2ME, но не во всех случаях.

  • Наконец самое страшное - MIDP 1.0 (да и MIDP 2.0) весьма ограничены и не могут использовать все возможности всех телефонов. Многие разработчики (например Nokia со своим Nokia UI) создают дополнительные библиотеки классов, которые расширяют возможности MIDP. Естественно у разных разработчиков эти классы свои и друг с другом они не совместимы, а использовать их приходится. 

Таким образом создать один мидлет для всех устройств, поддерживающих MIDP практически, невозможно. Скорее всего вам придется вносить в код и в оформление мидлета те или иные изменения для того, чтобы он правильно работал на нужной платформе и использовал ее возможности по максимуму. Исходя из всего вышесказанного, разрабатывайте ваши приложения таким образом, чтобы легче было в них потом что-то менять. Общие рекомендации:

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

  • Постарайтесь не использовать текстовые строки напрямую (например myGraphics.drawString ("Привет!", 10, 10, myGraphics.LEFT | myGraphics.TOP);). Лучше объявить все строки константами в одном месте, а потом использовать эти константы. Это облегчит вам перевод игры на другой язык (например с русского на английский).

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

Средства разработки

Для разработки мидлетов существует огромное количество софта. В любом случае кроме Java 2 SDK и собственно средства разработки вам понадобятся эмуляторы (вариант - SDK) для конкретных моделей телефонов. Лично я пользуюсь софтом от Sun, который доступен для бесплатного скачивания и использования (см.http://wireless.java.sun.com/allsoftware/). Итак, что нужно:

  • Java 2 Software Developer Kit (J2SDK) - набор средств разработки Java 2 приложений и аплетов (см. например http://java.sun.com/j2se/1.4.1/download.html). Используется средствами разработки мидлетов, которые фактически являются надстройкой над JDK.

  • Java 2 Resource Environment (JRE) - среда окружения и виртуальная машина Java2. Он может быть и не нужен, если ваше средство разработки обходится без него. Но например в Windows XP, где предустановленной JVM нет, он наверняка понадобится. Нужно заметить, что JRE всегда входит в состав J2SDK.

  • Какое-нибудь средство разработки (например Forte Studio ONE Mobile Edition Update 1 (похоже на то, что скачать ее больше нельзя %( ). Или можно поставить последнюю версию NetBeans и накинуть на нее модули для разработки мидлетов). Средств этих сейчас довольно много и кроме того большинство бесплатные.

  • Эмуляторы устройств, на которые разрабатывается мидлет. Их можно найти на сайтах разработчиков устройств (например http://forum.nokia.com). В большинстве случаев они легко интегрируются в средство разработки.

Программирование для платформы Nokia  

Nokia на мой взгляд является одним из передовых производителей телефонов в плане инноваций (и J2ME в том числе). На рынке телефонов Nokia представлена очень широко и если вы занимаетесь разработкой на J2ME, то под Nokia вам точно программировать придется. Итак приступим ;)

 

Телефоны Nokia c поддержкой J2ME разделены на серии. В рамках каждой серии есть общие особенности (например размер экрана, общие ограничения на размеры мидлета и памяти и т.п.). Основные серии, для которых выпускаются игры и приложения на J2ME, это Series 40 и Series 60. Телефоны обеих серий имеют цветной экран и позволяют использовать фирменный набор классов от Nokia - Nokia UI, о котором ниже. Телефоны Series 30 на мой взгляд внимания не заслуживают - это старые модели с небольшим черно-белым экраном (кроме 3510i), которых продается все меньше. Series 90 также распространена слабо.

 

-= Nokia UI =-

 

Этот набор классов естественно есть только у телефонов Nokia. Основные возможности, которые он дает:

Рисование на полный экран

Для этого необходимо наследовать вашу "рисовалку" не от Canvas, а от FullCanvas. При этом теряется возможность использовать команды (Command). FullCanvas выбрасывает исключения при попытке добавить команды или CommandListener, зато появляется возможность обработки кнопок экранного меню. В FullCanvas для этого определены константы KEY_SOFTKEY1, KEY_SOFTKEY2 (правая и левая) и KEY_SOFTKEY3 (нажатие на джойстик - у большинства телефонов Series 40 не используется). В остальном использование FullCanvas не отличается от обычного Canvas.

Возможность работы со звуком

Можно делать звуки вроде простой пищалки и даже проигрывать мелодии. Для этих целей нужно создавать объекты класса Sound. Простейший вариант - единичный звук с заданной частотой и длительностью - Sound(freq,duration). После создания можно вызывать метод play(int loop) - проиграть loop раз. Если 0, то будет проигрываться в цикле. Есть возможность проверять состояние Sounda'а, менять громкость и т.п. - смотрите документацию. Нас же интересует, как проигрывать простые мелодии и эффекты, взятые, например, из одноголосных MIDI.

Естьконструктор Sound(byte[] data,int type).По идее при помощи него можно и вавки проигрывать, но вавки слишком уж много места занимают, да и ни к чему это (уж поверьте мне) в современных телефонах. Итак, в качестве типа будем использовать Sound.FORMAT_TONE. При этом массив data должен быть в хитром формате, в котором я не разбирался. Впрочем, получить его очень просто. Для этого нам понадобится Nokia Developer's Suite. Там естьAudioConverter (вроде он еще и отдельно бывает). Так вот в нем открываете MIDI файл (желательно одноголосный), выбираете дорожку, нажимаете Convert и получаете то, что нужно - массив байтов! Заметьте, что инициализировать массив в программе так:

byte music[]={10,10,10,10,10};

не очень хорошо, так как это засоряет код (попробуйте дизассемблировать и заглянуть в конструктор). Лучше взять строку в шестнадцатеричном формате, разобрать ее, а потом уже использовать. Пример следует ниже. Да, кстати, одновременно может проигрываться только один Sound, мало того, если вы попробуете что-то поиграть, пока предыдущий звук не остановился, могут возникнуть проблемы (Exception хе-хе), хотя вроде как происходить этого не должно. Так что нужно следить за тем, чтобы проигрывался только один звук. Пример:

class MyClass{

 

 String dTest = "024a3a400400131e826c210350374492813a0000"; //Этоиз Audio Converter'а NDS

 Sound sTest;

 

 boolean soundOn=true; //чтобможнобылоотключатьзвук

 Sound curSound;

 void playSound(Sound s){

   if (soundOn && (s!=curSound || curSound.getState()!=Sound.SOUND_PLAYING)){

     try{

        if (curSound!=null)

          curSound.stop();

        curSound=s;

        curSound.play(1);

      }

     catch (Exception e){};

   }

 }

 

 static byte [] str2bytes(String s){ // разбирает строку шестнадцатеричных чисел (по два 

   byte []ret=new byte[s.length()/2]; // байта) и преобразует в байтовый массив

   for (int i=0;i<s.length();i++){

     if (i%2==0)ret[i/2]=0;

     char c=s.charAt(i);

     byte b=(byte)(c-'0');

     if (b>9)b=(byte)(c-'a'+10);

     if (i%2==0){

       ret[i/2]=0;

       b*=16;

     }

     ret[i/2]+=b;

   }

   return ret;

 }

 

 

 MyClass(){

   sTest=new Sound(str2bytes(dTest),Sound.FORMAT_TONE);

   playSound(sTest);

 }

 

};

 

Не стоит насыщать свои игры звуками (и уж тем более на фон что-то вешать) - будет тормозить.

 

Дополнительные возможности рисования

Для их использования нужно создавать объект классаDirectGraphics

DirectGraphics DirectUtils.getDirectGraphics(Graphics);

На DirectGraphics можно рисовать Image'ы с различными манипуляциями (повороты - только на углы, кратные 90 ;), отражения), треугольники, многоугольники, растеризовать массивы (см. ниже) и создавать массивы из изображений, а также устанавливать цвет в формате ARGB (между прочим в 60й серии поддерживается частичная прозрачность, и для Image'в тоже). Для подробностей см. документацию.

 

Доступ к пиксельной информации изображений

Можно создавать массивы из картинок (getPixels(...)), а потом отрисовывать эти массивы (drawPixels(...)). C параметрами сами разбирайтесь, но есть тут один нюанс. Последним параметром там идет формат. По идее этот формат можно получить методом DirectGraphics.getNativePixelFormat(), но этот метод возвращает не то! Нужно использовать DirectGraphics.TYPE_USHORT_4444_ARGB, и соответственно для хранения информации использовать short[]. Каждый элемент массива будет представлять цвет в виде 0xARGB.

 

Доступ к вибро и свету

Осуществляется через статические методы класса DeviceControl. Не забудьте брать их в try...catch! Например на Series40 почти все телефоны поддерживают доступ к вибро, но как оказалось не все. И на том, который не поддерживает, выбрасывается IllegalStateException.

 

Возможность создания картинок (Image) с прозрачным фоном

В DirectUtilsестьметод createImage(int width, int height,int backColor).Содается Image размером width X height, залитый цветом backColor, представленном в виде 0xAARRGGBB.

 

Документацию по NokiaUI можно найти на сайте Nokia или вместе с эмулятором в папке docs.

 

Кроме NokiaUI используются и другие расширения стандарта. Например, это Mobile Media API, которое настоятельно рекомендую использовать вместо NokiaUI, если это возможно.

 

Теперь глюки %) Глюки попадаются практически в любой реализации J2ME, так что будьте готовы.

 

  • В некоторых телефонах Nokia Series 60 какой бы цвет вы ни ставили при помощи Graphics.setColor(), при выводе текста методом Graphics.drawString() цвет всегда будет черным. 

  • Картинка с прозрачностью, созданная при помощи DirectUtils.createImage(width,height,color), будет терять прозрачность при попытке отрисовать ее на Graphics - нужно рисовать ее наDirectGraphics на телефонахSeries 60. 

  • Про звук с NokiaUI я уже сказал. 

  • При использовании MMAPI звуки иногда перестают проигрываться без всяких причин. Выход - останавливать все проигрываемые в данный момент звуки (точнее Player'ы, т.е. использовать функцию вроде playSound, приведенной выше), а для того, который вы хотите проиграть, вызывать setMediaTime(0) и setLoopCount(1) - иногда помогает %) 

  • Это не глюк, а скорее фича - в телефонах Series40 текст выводится на Graphics довольно медленно, т.е. если будет много текста, то будут тормоза. То же вроде справедливо для drawRect (совершенно не понятно, почему, кстати). В общем напишите программку, которая тестирует производительность на разных примитивах и переключении цветов и проверяйте ею телефоны. У меня такая есть - много интересного узнал %) 

  • Еще одна фишка – при использовании светлой текстуры иногда появляются светлые вертикальные полоски у правого края текстур, так что границы текстур становятся видны. Глюк можно наблюдать и на эмуляторе. Как с ним бороться – не знаю.

  • В телефоне Nokia 6600 (а возмоно и в других телефонах 60й серии с MIDP 2.0) методы из NokiaUI работают либо некорректно (например DirectGraphics.drawImage(...) на некоторых прошивках, также наблюдаются глюки с прозрачностью в getPixels(), drawPixes()), либо невероятно медленно (тот же drawPixels())! Выход - использовать метоы MIDP 2.0, которые почти полностью перекрывают возможности NokiaUI. Портироваться на MIDP 2.0 с NokiaUI очень просто.

Наверняка еще что-то есть, но я сейчас не помню, вспомню - напишу.

Использование обфускаторов

Сразу, чтобы подчеркнуть важность темы, приведу следующую аксиому: Если вы программируете на J2ME, то вы обязаны использовать обфускатор! 

Что же это такое? Обфускаторы (от английского obfuscate – сбивать с толку) использовались уже давно для запутывания java кода (class файлов) с целью затруднить их декомпиляцию. Дело в том, что в class файле все имена переменных, классов и т.п. хранятся в первоначальном виде и декомпилированый код практически ничем не отличается от исходного. Обфускаторы меняют все имена (переменных, классов и т.п.) на малопонятные (a, a1, a1_ и т.п.) и запутывают код (каждый по-своему). Это полезно само по себе, но есть еще один невероятно полезный в J2ME побочный эффект – при использовании обфускатора размер класса как правило значительно уменьшается! Можно получить экономию для мидлета в несколько килобайт, а это порой бывает жизненно необходимо. Обфускаторов много, какой из них выбрать – решайте сами. Можно попробовать применять несколько поочередно – эффект бывает как положительный, так и отрицательный. 

Я расскажу об использовании обфускатора самым тернистым способом – с командной строки – на примере Retroguard. Сам Retroguard поставляется в виде Java-программы, запакованной в Jar архив (retroguard.jar). Итак, командная строка для «обфусцировния» мидлета, написанного для NokiaSeries 40:

java -classpath .\;.\retroguard.jar;.\midpapi\N40\emptyapi.zip;.\midpapi\N40\classes.zip RetroGuard source.jar obfuscated.jar ignore.rgs

Разберем все по порядку.

В classpath перечислено следующее:

.\ - текущий каталог

\retroguard.jar – чтобы было доступно содержимое архива с обфускатором

\midpapi\N40\emptyapi.zip – пустой API. Зачем он нужен (здесь и вообще в составе WTK) я точно не знаю, но нужен точно, и стоять он должен именно перед classes.zip, а не после.

\midpapi\N40\classes.zip – классы API для конкретного устройства.

Откуда берутся последние два класса.

emptyapi.zip ищется в SDK для определенного телефона, а если там его нет, то берете его из папки WTKLib вашего WTK (сначала смотрите в WTK конкретного производителя, потом уже если нет, то в Sun’овском).

classes.zip – этот берется из папки lib из SDK конкретного телефона. Может называться api.jar, api.zip и т.п.

Есть один нюанс – для Series 60 я использую те же API, что и для Series 40, с родными почему-то не хочет обфускиваться.

Дальше

Retroguard – имя выполняемого класса (из jar архива).

source.jar – то, что вы хотите обфускать.

obfuscated.jar – результат операции.

ignore.rgs – это файл, содержащий список того, что нужно игнорировать. Пример – у вас есть пакет (package) local, в котором есть несколько картинок. Вы их в мидлете загружаете по имени (“/local/image.png”), но после обфускивания ретрогард все вынесет в корень и все пакеты уберет, так что картинка ваша не откроется и мидлет вылетит. Кроме того о структуре мидлетов ретрогард ничего не знает и без зазрения совести переименует ваш класс – наследник MIDlet во что-нибудь типа “a_1”, а так как у вас в jad записано, что мидлет у вас называется MyMIDlet, то такой мидлет вообще не запуститься. Выход – вы прописываете в ignore.rgs строчку

.class Container/MyMIDlet (MyMIDletздесьнаходитсявпакете Container).При этом сам класс обфусцируется, но не переименовывается и пакет (Container) также остается нетронутым.

После того, как процесс завершен, рекомендую зайти в получившийся архив и удалить из файла манифеста (META-INF/manifest.inf) лишнюю информацию. Дело в том, что ретрогард для каждого файла архива оставляет здесь информацию типа 

Name: Container/icons.png

SHA-Digest: Bscp3ElQeX4tUQklqxBTGku4xaU=

MD5-Digest: 0HGduAauhLh096rVpTV9QA==

Digest-Algorithms: SHA MD5 

Видимо для проверки целостности файлов архива. Но в J2ME эта информация лишняя, а для мидлетов под Siemens ее наличие и вовсе приводит к тому, что мидлет не запускается. Кроме того, ее удаление приведет к значительному уменьшению размера мидлета. Так что ее нужно удалить (не удалите лишнего!). Чтобы не мучаться с архиватором JAR, лучше всего поставить плагин 7zip в FAR и просто изменить манифест и автоматически перепаковать архив в режиме normal (уровень компрессии 6). 

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

preverify.exe -classpath .\midpapi\N40\classes.zip obfuscated.jar

Здесь classes.zip тот же, что и раньше, а obfuscated.jar – результат обфусциования. То, что получится будет в папке output.

Теперь остается переименовать результат в то имя, которое имеет jad файл исходного мидлета (source.jad), а затем зайти в jad файл и поставить в атрибут MIDlet-Jar-Size получившийся размер jar файла.

Слишком трудно? %) Есть возможность интегрировать обфускатор в среду разработки (см. например тут) – это просто, но я не пробовал, дерзайте сами.

АЛГОРИТМЫ

Введение

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

Парабола по трем точкам

Данная формула необходима для того, чтобы иметь зависимость y(x), которая соответствует параболе, проходящей через три заданные точки. Координаты этих точек - (x0,y0),(x1,y1) и (x2,y2).

 

Применений можно придумать много. Например в одной игре у меня лягушки прыгали с листика на листик по параболе. Делалось это так: первая координата - текущее положение лягушки, третья - то, в которое она попадет после прыжка, а вторая - ((x2+x0)/2;max(y2,y0)+h), где h - высота полета (в данном случае она была отрицательная, т.к. ось oy направлена вниз) в точке (x1,y1). Получались весьма красивые прыжки %)

Целочисленный квадратный корень

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

static int sqrt(int n){
  int temp,div;
  int ret=n;
  if (n<=0)return 0; 
  if ((n & 0xFFFF0000) >0){
    if ((n & 0xFF000000) >0)div=0x3FFF;
    else div=0x3FF;
  }
  else{
    if ((n & 0xFF00) >0)div=0x3F;
    else div= (n>4 ? 0x7 : n);
  }
  while (true){
    temp=n/div+div;
    div=temp/2;
    div+=(temp & 1);
    if (ret > div)ret=div;
    else{
      if (n/ret == ret-1 && n%ret==0)ret--;
      return ret;
    }
  }
}

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

Hosted by uCoz