<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	
	xmlns:georss="http://www.georss.org/georss"
	xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#"
	>

<channel>
	<title>Topic touch screen | Hey, ruX is here.</title>
	<atom:link href="https://rux.vc/tags/touch-screen/feed/" rel="self" type="application/rss+xml" />
	<link>https://rux.vc</link>
	<description>Delivering things - from code to product</description>
	<lastBuildDate>Thu, 03 Jun 2010 08:30:08 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.4.8</generator>
<site xmlns="com-wordpress:feed-additions:1">162978439</site>	<item>
		<title>j2me: пример с падающим мячиком</title>
		<link>https://rux.vc/2010.05/j2me-example-falling-ball/</link>
					<comments>https://rux.vc/2010.05/j2me-example-falling-ball/#comments</comments>
		
		<dc:creator><![CDATA[ruX]]></dc:creator>
		<pubDate>Sun, 16 May 2010 10:50:04 +0000</pubDate>
				<category><![CDATA[Articles]]></category>
		<category><![CDATA[Coding]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[ball]]></category>
		<category><![CDATA[canvas]]></category>
		<category><![CDATA[cldc]]></category>
		<category><![CDATA[events]]></category>
		<category><![CDATA[example]]></category>
		<category><![CDATA[graphics]]></category>
		<category><![CDATA[graviation]]></category>
		<category><![CDATA[j2me]]></category>
		<category><![CDATA[keyboard]]></category>
		<category><![CDATA[MIDlet]]></category>
		<category><![CDATA[mobile]]></category>
		<category><![CDATA[netbeans]]></category>
		<category><![CDATA[p1i]]></category>
		<category><![CDATA[touch screen]]></category>
		<category><![CDATA[video]]></category>
		<guid isPermaLink="false">http://rux.pp.ru/blog/?p=581</guid>

					<description><![CDATA[<p>Хочу поделиться одним своим примером приложения для мобильной java. Основная задача - понять как пишутся такие приложения под телефоны. Вроде задачу выполнил :). В программке можно передвигать мяч, падающий в "гравитационном" поле по законам физики(надеюсь), задавать его скорость и направление движения, как водя по сенсорному экрану телефона(если есть) так и кнопками В эмуляторе выглядит всё ... <a title="j2me: пример с падающим мячиком" class="read-more" href="https://rux.vc/2010.05/j2me-example-falling-ball/" aria-label="More on j2me: пример с падающим мячиком">Read more</a></p>
The post <a href="https://rux.vc/2010.05/j2me-example-falling-ball/">j2me: пример с падающим мячиком</a> first appeared on <a href="https://rux.vc">Hey, ruX is here.</a>.]]></description>
										<content:encoded><![CDATA[<p>Хочу поделиться одним своим примером приложения для мобильной java. Основная задача - понять как пишутся такие приложения под телефоны. Вроде задачу выполнил :). В программке можно передвигать мяч, падающий в "гравитационном" поле по законам физики<em>(надеюсь)</em>, задавать его скорость и направление движения, как водя по сенсорному экрану телефона(если есть) так и кнопками</p>
<p>В эмуляторе выглядит всё не так красиво, как в живую, поэтому продемонстрирую на телефоне(SE P1i)<br />
<center><br />
<object width="425" height="344"><param name="movie" value="http://www.youtube.com/v/my3Wu-z5bsI&hl=ru&fs=1"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param></object><br />
</center><br />
Понравилось? Для начала работы с j2me - самое то.<br />
Используется <strong>MIDP-2.0</strong>, <strong>CLDC-1.1</strong>.
</p>
<p><span id="more-581"></span></p>
<h2>Структура приложения</h2>
<ul>
<li>В <em>/resource/</em> лежат <span style="mycomment" title=":D">как ни странно ресурсы</span> - картинки</li>
<li>В <em>/ru/pp/rux/fallingball</em> находится сам мидлет. Он имеет несколько public static методов для доступа к нему извне, например когда требуется завершить работу или установить другой <strong>Displayable</strong></li>
<li>В <em>/ru/pp/rux/fallingball/util</em> есть пара классов, которые помогают в работе. Это <strong>ColorGradient</strong>, рисующий градиент и <strong>SomeMath</strong>, реализующий математические функции(<strong>atan</strong>, <strong>pow</strong>, <strong>exp</strong>), которых нет в j<strong>ava.lang.Math в MicroEdition</strong>, а эти функции необходимы для расчёта физики</li>
<li><a href="http://rux.pp.ru/blog/wp-content/uploads/2010/05/fallingball-welcome-screen.png" data-lightboxplus="lightbox[581]" title="FallingBal: welcome screen"><img decoding="async" src="http://rux.pp.ru/blog/wp-content/uploads/2010/05/fallingball-welcome-screen-67x150.png" alt="" title="FallingBal: welcome screen" width="67" height="150" class="alignright size-thumbnail wp-image-585" srcset="https://rux.vc/wp-content/uploads/2010/05/fallingball-welcome-screen-67x150.png 67w, https://rux.vc/wp-content/uploads/2010/05/fallingball-welcome-screen-135x300.png 135w, https://rux.vc/wp-content/uploads/2010/05/fallingball-welcome-screen.png 300w" sizes="(max-width: 67px) 100vw, 67px" /></a>Канавы лежат в <em>/ru/pp/rux/fallingball/canvas</em>. Первая, самая простая, представляющая собой welcome screen - это класс <strong>WelcomeCanvas</strong>, на нём отображается приветствие - в центре экрана мячик, снизу надпись "нажмите куда-нибудь". Перед переходом к классу в котором происходит основное действо, настоятельно рекомендую ознакомиться с экраном приветствия, особенно если это ваши первые попытки изучать ME. Внешний вид - справа.
<p> В <strong>FallingBall</strong> классе происходит самое интересное - рисование мяча, обработка событий клавиатуры и нажатия на экран. Там достаточно много различных методов и полей, я взял на себя смелость не комментировать их - действительно некогда, но дал внятные имена.</li>
</ul>
<h2>Пристальный взгляд на FallingBall</h2>
<p>По таймеру, который срабатывает <strong>1000/20</strong> раз в секунду выполняется задание <strong>PhysicsTimer</strong>, которое производит обсчёт физики, если разрешенно полем <strong>enabePhysics</strong>. Запрещено может быть только когда нажата клавиша на клавиатуре или нажат экран. Глядя методы <strong>keyPressed</strong>/<strong>keyReleased</strong>, <strong>pointerDragged</strong>/<strong>pointerReleased</strong> видно, что там меняется значение этого флажка.</p>
<p>Во время движения мячика "руками" по экрану, не важно чем - кнопками или касанием экрана вычисляется новый вектор скорости. Для этого во время (первого) нажатия запоминается текущее положение, а после отпускания экрана, кнопки(нужное подчеркнуть), происходит вычисления - новый угол и скорость. Это происходит в методе<strong> recalculateSpeed(int x, int y, boolean sum)</strong>, принимающий новое положение мяча(места на котором стал мяч, после отпускания клавиши) и флажок - пересчитанную скорость нужно добавлять к существующий(нужно когда были нажатия клавиш) или заменять(когда установка нового вектора скорости была с помощью сенсорного экрана)<br />
<code lang="java"><br />
    protected void recalculateSpeed(int x, int y, boolean sum) {<br />
        if ( !(x &gt; startX - 2 &amp;&amp; x &lt; startX + 2) &amp;&amp; !(y &gt; startY - 2 &amp;&amp; y &lt; startY + 2) ) {<br />
            double d;<br />
            d = x - startX;<br />
            vx = (float) SomeMath.log(SomeMath.pow(d, 4)) * (d &gt; 0 ? 1 : -1) + (sum ? vx : 0);<br />
            d = y - startY;<br />
            vy = (float) SomeMath.log(SomeMath.pow(d, 4)) * ( d &gt; 0 ? 1 : -1) + (sum ? vx : 0);<br />
        }<br />
    }<br />
</code><br />
Немного странно выглядит? И логарифмы и степень. Нужно просто посмотреть на график логарифма и станет ясно почему я так сделал.<br />
<img decoding="async" src="http://rux.pp.ru/blog/wp-content/uploads/2010/05/logarithm-graph.png" alt="" title="Logarithm graph" width="200" height="205" class="alignright size-full wp-image-582" srcset="https://rux.vc/wp-content/uploads/2010/05/logarithm-graph.png 200w, https://rux.vc/wp-content/uploads/2010/05/logarithm-graph-146x150.png 146w" sizes="(max-width: 200px) 100vw, 200px" /><br />
Если было не большое перемещение, то нужно чтоб скорость мяча была небольшой. При среднем перемещении - средняя. А вот при большом перемещении(например с середины экрана до низу) скорость должна быть больше средней, но не так, чтоб за мячом было не уследить. Иначе говоря это попытка ввести некое сопротивление, пускай воздушное. В общем смотрим график справа</p>
<p>Разумеется, нужно предусмотреть команды выхода из приложения, а так же "о приложении". Для этого в конструкторе добавим их соответственно и объявим внутренний класс <strong>CommadsProcessor</strong>, который будет слушать что ему поступило. Кстати, в качестве <strong>About</strong> используется <strong>Alert</strong> с картинкой(а на картинке qr-code с адресом сайта:))<br />
<code lang="java"><br />
    class CommandsProcessor implements CommandListener {<br />
        public void commandAction(Command c, Displayable d) {<br />
            switch (c.getCommandType()) {<br />
            case Command.EXIT:<br />
                SmallMidlet.getInstance().notifyDestroyed();<br />
                break;<br />
            case Command.HELP:<br />
                showAbout();<br />
                break;<br />
            }<br />
        }<br />
    }<br />
</code><br />
Для создания About используется следующий singleton - метод:<br />
<code lang="java"><br />
    protected Alert getAbout() {<br />
        if (about == null) {<br />
            Image qrcode;<br />
            try {<br />
                qrcode = Image.createImage(&quot;/resource/rux.pp.ru.png&quot;);<br />
            } catch (IOException ex) {<br />
                qrcode = null;<br />
            }<br />
            about = new Alert(&quot;About..&quot;, &quot;http://ruX.pp.ru&quot;, qrcode, AlertType.INFO);<br />
            about.setTimeout(20000); // shown for 20 seconds</p>
<p>            Command back = new Command(&quot;Go back&quot;, Command.BACK, 1);<br />
            about.addCommand(back);<br />
        }<br />
        return about;<br />
    }</p>
<p></code>
</p>
<p>Методы <strong>move*</strong> занимаются перемещением мяча на заданное смещение, при этом проверяется возможность перемещения границами. Если перемещение не удалось, то методы возвращают false. Это и использует метод <strong>CommandsProcessor.run()</strong> - если в сдвинуть не получается, значит мяч долетел до какой то преграды и нужно изменить направления. Стенки экрана не идеально упругие - на них теряется 30% "кинетической энергии". А так же вводится гравитация, просто добавлением коэф ускорения - я подобрал 0.45. Просто из формулы <u>v = v<sub>0</sub> + a*t </u>(спасибо, Frozen). <strong>t</strong> у нас нет, но подразумевается, таймер же срабатывает через определённое время.<br />
<code lang="java"><br />
    class PhysicsTimer extends TimerTask {<br />
        public void run(){<br />
            if (!enablePhysics) return;</p>
<p>            if (!moveY((int)(vy))) vy *= -0.7;<br />
            if (!moveX((int)(vx))) vx *= -0.7;</p>
<p>            vy += 0.45;</p>
<p>            repaint();<br />
        }<br />
    }<br />
</code>
</p>
<p><strong>keyRepeated</strong>() - длинный метод, который просто выбирает направление движения, в зависимости от нажатой кнопки(сначала проверяется на игровую кнопку, если не нашёл то на нажатую клавишу). Также в нем считается коэф. <strong>repeatKoeff</strong> позволяющий перемещать мяч с ускорением при нажатии на кнопку - с каждым разом он не на много увеличивается, но в целом это заметно. <strong>repeatKoeff</strong> показывает на сколько пикселей переместится в следующий раз мяч. Как только повторения нажатия прекратились, он сразу же обнуляется в <strong>defaultRepeatKoeff</strong></p>
<p>Если имел место двойной хлопок по экрану(за время меньшее <strong>doubleTapInterval</strong>) срабатывает событие двойного нажатия - происходит обнуление скоростей по обоим осям(<strong>vx</strong>, <strong>vy</strong>), после этого на мяч действует только ускорение свободного падения. После каждого <s>хлопка</s> касания  по экрану сохраняется текущее время в милисекундах в lastTap.
</p>
<p>Ну и теперь весь код <strong>FallingBall</strong>, остальные файлы в архиве ниже<br />
<code lang="java" width="700"></p>
<p>package ru.pp.rux.fallingball.canvas;</p>
<p>import java.io.IOException;<br />
import java.util.Calendar;<br />
import java.util.Timer;<br />
import java.util.TimerTask;<br />
import javax.microedition.lcdui.Alert;<br />
import javax.microedition.lcdui.AlertType;<br />
import javax.microedition.lcdui.Canvas;<br />
import javax.microedition.lcdui.Command;<br />
import javax.microedition.lcdui.CommandListener;<br />
import javax.microedition.lcdui.Displayable;<br />
import javax.microedition.lcdui.Graphics;<br />
import javax.microedition.lcdui.Image;</p>
<p>import ru.pp.rux.fallingball.SmallMidlet;<br />
import ru.pp.rux.fallingball.util.ColorGradient;<br />
import ru.pp.rux.fallingball.util.SomeMath;</p>
<p>/**<br />
 *<br />
 * @author ruX[Ruslan Zaharov]<br />
 * 2010 (c) http://ruX.pp.ru<br />
 */<br />
public class FallingBall extends Canvas {</p>
<p>    private Image background = null;<br />
    private Alert about = null;<br />
    private Image imgBall;</p>
<p>    private boolean enablePhysics = true;<br />
    private int x, y;<br />
    private float vx = 0, vy = 0;</p>
<p>    private int startX, startY;</p>
<p>    private final float defaultRepeatKoeff = 2.0F;<br />
    private float repeatKoeff = defaultRepeatKoeff;</p>
<p>    private final int doubleTapInterval = 400; // ms<br />
    private long lastTap;</p>
<p>    public FallingBall() {<br />
        setFullScreenMode(true);<br />
        x = getWidth() / 2;<br />
        y = getHeight() / 2;</p>
<p>        new Timer().scheduleAtFixedRate(new PhysicsTimer(), 500, 1000/20);<br />
        setCommandListener(new CommandsProcessor());<br />
        addCommand(new Command(&quot;Exit&quot;, Command.EXIT, 0));<br />
        addCommand(new Command(&quot;About&quot;, Command.HELP, 1));<br />
        repaint();<br />
    }</p>
<p>    protected Image getBackground() {<br />
        if (background == null) {<br />
            background = Image.createImage(getWidth(), getHeight());<br />
            ColorGradient.draw(background.getGraphics(), 0, 0, getWidth(), getHeight(),<br />
                    0xAA, 0x22, 0x00, 0x22, 0xEE, 0x00);<br />
        }<br />
        return background;<br />
    }</p>
<p>    protected Image getBall()  {<br />
        if (imgBall == null) {<br />
            try {<br />
                imgBall = Image.createImage(&quot;/resource/ball.png&quot;);<br />
            } catch (IOException ex) {<br />
                ex.printStackTrace();<br />
            }<br />
        }<br />
        return imgBall;<br />
    }</p>
<p>    protected Alert getAbout() {<br />
        if (about == null) {<br />
            Image qrcode;<br />
            try {<br />
                qrcode = Image.createImage(&quot;/resource/rux.pp.ru.png&quot;);<br />
            } catch (IOException ex) {<br />
                qrcode = null;<br />
            }<br />
            about = new Alert(&quot;About..&quot;, &quot;http://ruX.pp.ru&quot;, qrcode, AlertType.INFO);<br />
            about.setTimeout(20000); // shown for 20 seconds</p>
<p>            Command back = new Command(&quot;Go back&quot;, Command.BACK, 1);<br />
            about.addCommand(back);<br />
        }<br />
        return about;<br />
    }</p>
<p>    protected void showAbout() {<br />
        SmallMidlet.getDisplay().setCurrent(getAbout(), this);<br />
    }</p>
<p>    protected void paint(Graphics g) {<br />
        g.drawImage(getBackground(), 0, 0, 0);<br />
        g.drawImage(getBall(), x - getBall().getWidth()/2, y - getBall().getHeight()/2, 0);<br />
        double length = Math.sqrt(SomeMath.pow(x - startX, 2) + SomeMath.pow(y - startY, 2));<br />
        double arrowlength = 14;<br />
        if (!enablePhysics &amp;&amp; (length &gt; getBall().getHeight()/2+arrowlength)) {<br />
            // ok.. lets begin to draw arrowhead<br />
            double angle = SomeMath.aTan2(y - startY, x - startX);<br />
            length -= getBall().getHeight() / 2;<br />
            int tx = (int)(startX + length * Math.cos(angle));<br />
            int ty = (int)(startY + length * Math.sin(angle));;</p>
<p>            g.setColor(0, 0, 0);<br />
            g.drawLine(startX, startY, tx, ty);<br />
            g.drawLine(startX+1, startY, tx+1, ty);<br />
            g.drawLine(startX, startY+1, tx, ty+1);<br />
            g.drawLine(startX+1, startY+1, tx+1, ty+1);</p>
<p>            double arrowdeg = Math.PI / 8;<br />
            int x1 = (int)(tx - arrowlength * Math.cos(angle - arrowdeg));<br />
            int y1 = (int)(ty - arrowlength * Math.sin(angle - arrowdeg));<br />
            int x2 = (int)(tx - arrowlength * Math.cos(angle + arrowdeg));<br />
            int y2 = (int)(ty - arrowlength * Math.sin(angle + arrowdeg));</p>
<p>            g.drawLine(tx, ty, x1, y1);<br />
            g.drawLine(tx, ty, x2, y2);<br />
            g.drawLine(x1, y1, x2, y2);</p>
<p>            g.setColor(0xffffff);<br />
            g.fillTriangle(tx, ty, x1, y1, x2, y2);<br />
        }<br />
    }</p>
<p>    protected boolean moveX(int offset) {<br />
        if (offset &gt; 0) {<br />
            if (x &gt; getWidth() - getBall().getWidth() / 2 - offset) return false;<br />
        } else {<br />
            if (x &lt;  - offset + getBall().getWidth() / 2) return false;<br />
        }<br />
        x += offset;<br />
        return true;<br />
    }</p>
<p>    protected boolean moveY(int offset) {<br />
        if (offset &gt; 0) {<br />
            if (y &gt; getHeight() - getBall().getHeight() / 2 - offset) return false;<br />
        } else {<br />
            if (y &lt;  - offset + getBall().getHeight() / 2) return false;<br />
        }<br />
        y += offset;<br />
        return true;<br />
    }</p>
<p>    protected boolean moveXY(int offx, int offy) {<br />
        return moveX(offx) | moveY(offy);<br />
    }</p>
<p>    protected void setXY(int nx, int ny) {<br />
        x = nx;<br />
        y = ny;<br />
    }</p>
<p>    protected void keyPressed(int key) {<br />
        if (key == Canvas.KEY_STAR) {<br />
            showAbout();<br />
            return;<br />
        }<br />
        enablePhysics = false;<br />
        startX = x; startY = y;<br />
        keyRepeated(key);<br />
    }</p>
<p>    protected void keyRepeated(int key) {<br />
        if (enablePhysics) return;</p>
<p>        int rk = (int)repeatKoeff;<br />
        switch (getGameAction(key)) {<br />
        case Canvas.DOWN:<br />
            moveY(rk);<br />
            break;<br />
        case Canvas.UP:<br />
            moveY(-rk);<br />
            break;<br />
        case Canvas.RIGHT:<br />
            moveX(rk);<br />
            break;<br />
        case Canvas.LEFT:<br />
            moveX(-rk);<br />
            break;<br />
        default:<br />
            switch (key) {<br />
            case Canvas.KEY_NUM1:<br />
                moveXY(-rk, -rk);<br />
                break;<br />
            case Canvas.KEY_NUM2:<br />
                moveY(-rk);<br />
                break;<br />
            case Canvas.KEY_NUM3:<br />
                moveXY(rk, -rk);<br />
                break;<br />
            case Canvas.KEY_NUM4:<br />
                moveX(-rk);<br />
                break;<br />
            case Canvas.KEY_NUM6:<br />
                moveX(rk);<br />
                break;<br />
            case Canvas.KEY_NUM7:<br />
                moveXY(-rk, rk);<br />
                break;<br />
            case Canvas.KEY_NUM8:<br />
                moveY(rk);<br />
                break;<br />
            case Canvas.KEY_NUM9:<br />
                moveXY(rk, rk);<br />
                break;<br />
            }</p>
<p>        }</p>
<p>        repaint();<br />
        repeatKoeff *= 1.1F;<br />
    }</p>
<p>    protected void keyReleased(int key) {<br />
        enablePhysics = true;<br />
        recalculateSpeed(x, y, true);<br />
        repeatKoeff = defaultRepeatKoeff;<br />
    }</p>
<p>    protected void pointerPressed(int x, int y) {<br />
        long now = Calendar.getInstance().getTime().getTime();<br />
        setXY(x, y);<br />
        if (now - lastTap &lt; doubleTapInterval) {<br />
            // double-tap?<br />
            vx = vy = 0;<br />
            return;<br />
        }<br />
        startX = x; startY = y;<br />
        lastTap = now;<br />
    }</p>
<p>    protected void pointerDragged(int x, int y) {<br />
        enablePhysics = false;<br />
        setXY(x, y);<br />
        repaint();<br />
    }</p>
<p>    protected void pointerReleased(int x, int y) {<br />
        recalculateSpeed(x, y, false);<br />
        enablePhysics = true;<br />
    }</p>
<p>    protected void recalculateSpeed(int x, int y, boolean sum) {<br />
        if ( !(x &gt; startX - 2 &amp;&amp; x &lt; startX + 2) &amp;&amp; !(y &gt; startY - 2 &amp;&amp; y &lt; startY + 2) ) {<br />
            double d;<br />
            d = x - startX;<br />
            vx = (float) SomeMath.log(SomeMath.pow(d, 4)) * (d &gt; 0 ? 1 : -1) + (sum ? vx : 0);<br />
            d = y - startY;<br />
            vy = (float) SomeMath.log(SomeMath.pow(d, 4)) * ( d &gt; 0 ? 1 : -1) + (sum ? vx : 0);<br />
        }<br />
    }</p>
<p>    class PhysicsTimer extends TimerTask {<br />
        public void run(){<br />
            if (!enablePhysics) return;</p>
<p>            if (!moveY((int)(vy))) vy *= -0.7;<br />
            if (!moveX((int)(vx))) vx *= -0.7;</p>
<p>            vy += 0.45;</p>
<p>            repaint();<br />
        }<br />
    }</p>
<p>    class CommandsProcessor implements CommandListener {<br />
        public void commandAction(Command c, Displayable d) {<br />
            switch (c.getCommandType()) {<br />
            case Command.EXIT:<br />
                SmallMidlet.getInstance().notifyDestroyed();<br />
                break;<br />
            case Command.HELP:<br />
                showAbout();<br />
                break;<br />
            }<br />
        }<br />
    }<br />
}<br />
</code>
</p>
<h2>Files</h2>
<ul>
<li><a href='http://rux.pp.ru/blog/wp-content/uploads/2010/05/FallingBall.tar.gz'>FallingBall.tar</a> - проект создан под NetBeans 6.8</li>
<li>А так же откомпилированный <a href='/blog/wp-content/uploads/2010/05/FallingBall.jar'>FallingBall.jar</a> и файл описания <a href='/blog/wp-content/uploads/2010/05/FallingBall.jad'>FallingBall.jad</a></li>
</ul>
<h2>Final</h2>
<p>Надеюсь этот пример, несколько сложнее helloWorld окажется кому - то полезным. Хотя уже оказался - мне.</p>
<p>В этом исходнике большое поле для экспериментов - можно дописать нечто бильярда с одной дыркой, которая ездит вдоль периметра с большой скоростью, к примеру, немного приложить фантазию нужно всего лишь . Если кто нибудь возьмётся(опять же в учебных для себя целях), сообщайте!</p>The post <a href="https://rux.vc/2010.05/j2me-example-falling-ball/">j2me: пример с падающим мячиком</a> first appeared on <a href="https://rux.vc">Hey, ruX is here.</a>.]]></content:encoded>
					
					<wfw:commentRss>https://rux.vc/2010.05/j2me-example-falling-ball/feed/</wfw:commentRss>
			<slash:comments>3</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">581</post-id>	</item>
	</channel>
</rss>
