diff --git a/src/About.java b/src/About.java
new file mode 100644
index 0000000..452384f
--- /dev/null
+++ b/src/About.java
@@ -0,0 +1,215 @@
+/*
+ * aNNiMON 2010
+ * For more info visit http://annimon.com/
+ */
+
+/*
+ * На основе класса MultiLineText от А.С. Ледкова
+ * www.mobilab.ru
+ */
+import com.emos.ui.ESkin;
+import com.emos.ui.StringEncoder;
+import java.io.DataInputStream;
+import java.util.Vector;
+import javax.microedition.lcdui.*;
+
+public class About extends Canvas {
+
+ private final String path = "about.ru";
+ private Font def, fnt;
+ private int fontHeight, defHeight;
+ private String str; //текст
+ private int w, h; //размеры
+
+ private int mh; //Размер ограничивающего прямоугольника;
+ private int y0; //Положение верхнего края текста
+ private int dy; //Шаг при прокрутке текста
+ private int textheight; //Общая высота текста
+ private Vector strLines;
+
+ public About() {
+ setFullScreenMode(true);
+ w = getWidth();
+ h = getHeight();
+ str = getText(path);
+ fnt = Font.getFont(Font.FACE_MONOSPACE, Font.STYLE_BOLD, Font.SIZE_SMALL);
+ def = Font.getDefaultFont();
+ fontHeight = fnt.getHeight()+2;
+ dy = defHeight = def.getHeight()+2;
+ //
+ //15;
+ mh = h - fontHeight - 1;
+ SetTextPar();
+ }
+
+ protected void paint(Graphics g) {
+ int hc = h/2;
+ ESkin.drawVGradient (g, ESkin.wBack, ESkin.wBack2, 0,0, w,hc);
+ ESkin.drawVGradient (g, ESkin.wBack2, ESkin.wBack, 0,hc,w,h-hc);
+ ESkin.drawHGradient(g, ESkin.wTitle, ESkin.lBack, 0, 0, w, fontHeight);
+ g.setFont(fnt);
+ g.setColor(ESkin.wTitle);
+ g.drawString("RayCanvas", w/2, 1, 17);
+ g.setFont(def);
+ g.setClip(0, fontHeight+1, w, mh);
+ int y1 = y0;
+ for (int i = 0; i < strLines.size(); i++) {
+ if ((y1 + defHeight) > 0) {
+ g.drawString(strLines.elementAt(i).toString(), 1, fontHeight + 5 + y1, Graphics.LEFT | Graphics.TOP);
+ }
+ y1 = y1 + defHeight;
+ if (y1 > mh) {
+ break;
+ }
+ }
+ g.setClip(0, 0, w, h);
+ }
+
+ protected void keyPressed(int key) {
+ int ga = getGameAction(key);
+ if(ga==UP) MoveUp();
+ else if(ga==DOWN) MoveDown();
+ else if(ga==LEFT) PageUp();
+ else if(ga==RIGHT) PageDown();
+ else if(ga==FIRE || key==-6 || key==-7)
+ Main.midlet.dsp.setCurrent(Main.midlet.mn);
+ repaint();
+ }
+
+ protected void pointerPressed(int x, int y) {
+ int w3 = w/3;
+ int h3 = h/3;
+ if(y
w3 && x<(w-w3))) keyPressed(UP);
+ else if(y>(h-h3) && (x>w3 && x<(w-w3))) keyPressed(DOWN);
+
+ if(xh3 && y<(h-h3))) keyPressed(LEFT);
+ else if(x>(w-w3) && (y>h3 && y<(h-h3))) keyPressed(RIGHT);
+
+ else if(x(h-h3)) keyPressed(-6);
+ else if(x>(w-w3) && y>(h-h3)) keyPressed(-7);
+ else if( (x>w3 && x<(w-w3)) && (y>h3 && y<(h-h3)) ) keyPressed(FIRE);
+ }
+
+ private void SetTextPar() {
+ //Разбиваем строку на массив строк
+ strLines = null;
+ strLines = new Vector();
+ String[] arr = splitString(str, "\n");
+ for(int i=0; i w) {//Слово полностью не умещается в строке
+ space = i0;
+ while (jw > w) {
+ j = 0;
+ while (j < w) {
+ space++;
+ j = def.stringWidth(substr.substring(in, space));
+ }
+ space = space - 1;
+ j = def.stringWidth(substr.substring(in, space));
+ strLines.addElement(substr.substring(in, space));
+ jw = jw - j;
+ i0 = space;
+ in = space;
+ }
+ jw = 0;
+ } else {
+ i0 = space;
+ }
+ }
+ }
+ strLines.addElement(substr.substring(in, imax));
+ }
+ textheight = strLines.size() * defHeight;
+ }
+
+ private String getText(String path) {
+ DataInputStream dis = new DataInputStream(getClass().getResourceAsStream(path));
+ StringBuffer strBuff = new StringBuffer();
+ int ch = 0;
+ try {
+ while ((ch = dis.read()) != -1) {
+ strBuff.append(StringEncoder.decodeCharCP1251((byte)ch));
+ }
+ dis.close();
+ } catch (Exception e) {e.printStackTrace();}
+ return strBuff.toString();
+ }
+
+ private void MoveDown() {
+ if (textheight > mh) {
+ y0 = y0 - dy;
+ if (mh - y0 > textheight) {
+ y0 = mh - textheight;
+ }
+ }
+ }
+
+ private void MoveUp() {
+ if (textheight > mh) {
+ y0 = y0 + dy;
+ if (y0 > 0) {
+ y0 = 0;
+ }
+ }
+
+ }
+
+ private void PageUp() {
+ if (textheight > mh) {
+ y0 = y0 + mh;
+ if (y0 > 0) {
+ y0 = 0;
+ }
+ }
+
+ }
+
+ private void PageDown() {
+ if (textheight > mh) {
+ y0 = y0 - mh;
+ if (mh - y0 > textheight) {
+ y0 = mh - textheight;
+ }
+ }
+ }
+
+ private String[] splitString(String str, String delim) {
+ if (str.equals("") || delim == null || delim.length() == 0) return new String[]{str};
+ String[] s;
+ Vector v = new Vector();
+ int pos = 0;
+ int newpos = str.indexOf(delim, 0);
+
+ while (newpos != -1) {
+ v.addElement(str.substring(pos, newpos));
+ pos = newpos + delim.length();
+ newpos = str.indexOf(delim, pos);
+ }
+ v.addElement(str.substring(pos));
+
+ s = new String[v.size()];
+ v.copyInto(s);
+ return s;
+ }
+
+}
diff --git a/src/Grid.java b/src/Grid.java
index c0dfe6c..8f8d42e 100644
--- a/src/Grid.java
+++ b/src/Grid.java
@@ -55,6 +55,8 @@ public class Grid {
// the entrance to the maze is at (0,1).
mySquares[0][1] = 0;
createMaze();
+ mySquares[mySquares.length-2][mySquares[0].length-4] = 5;
+ mySquares[mySquares.length-2][mySquares[0].length-2] = 5;
mySquares[mySquares.length-2][mySquares[0].length-3] = 5;
mySquares[mySquares.length-1][mySquares[0].length-3] = 5;
}
@@ -197,7 +199,7 @@ public class Grid {
* @param upper the upper bound for the random int.
* @return a random non-negative int less than the bound upper.
*/
- private int getRandomInt(int upper) {
+ public int getRandomInt(int upper) {
int retVal = myRandom.nextInt() % upper;
if (retVal < 0) {
retVal += upper;
diff --git a/src/Main.java b/src/Main.java
index fbd6e0c..330665b 100644
--- a/src/Main.java
+++ b/src/Main.java
@@ -6,7 +6,8 @@ public class Main extends MIDlet {
public Display dsp;
public static Main midlet;
- private RayCanvas canvas;
+ public Menu mn;
+
public Main() {
dsp = Display.getDisplay(Main.this);
@@ -14,9 +15,8 @@ public class Main extends MIDlet {
}
public void startApp() {
- canvas = new RayCanvas();
- dsp.vibrate(1000);
- dsp.setCurrent(canvas);
+ mn = new Menu();
+ dsp.setCurrent(mn);
}
public void pauseApp() {
diff --git a/src/Menu.java b/src/Menu.java
new file mode 100644
index 0000000..3a2774d
--- /dev/null
+++ b/src/Menu.java
@@ -0,0 +1,94 @@
+/*
+ * aNNiMON 2011
+ * For more info visit http://annimon.com/
+ */
+
+import com.emos.ui.*;
+import java.util.Random;
+import javax.microedition.lcdui.Graphics;
+
+/**
+ *
+ * @author aNNiMON
+ */
+public class Menu extends EWindow {
+
+ private String[] m1;
+ private int fh, cu, yy, d;
+ private Random rnd;
+ private long ty;
+
+ private RayCanvas ray;
+
+ public Menu() {
+ super("RayCanvas");
+ m1 = new String[] {
+ "Начать",
+ "Об игре",
+ "Выход",
+ };
+ rnd = new Random();
+ ray = new RayCanvas();
+ ESkin e = new ESkin(rnd.nextInt()%0xFFFFFF);
+ fh = EConst.mainFont.getHeight()+2;
+ yy = cu = 0;
+ d = hh/6;
+ }
+
+ protected void showNotify() {
+ ESkin e = new ESkin(rnd.nextInt()%0xFFFFFF);
+ }
+
+
+ public void paint(Graphics g, int w, int h) {
+ int hc = d+yy+cu*fh;
+ g.setFont(EConst.mainFont);
+ for (int i = 0;i0) yy-=2;
+ if(yy>1 || yy<-1) redraw();
+ }
+
+ public void keyEvent(int key, byte state) {
+ if(state!=RELEASED) {
+ int ga = getGameAction(key);
+ if (ga==UP && cu>0) {cu--; yy=fh;}
+ else if (ga==DOWN && cu(h-h3)) keyEvent(-6, PRESSED);
+ else if(x>(w-w3) && y>(h-h3)) keyEvent(-7, PRESSED);
+ else{
+ int cu1=cu;
+ y-=hc;
+ if(y>0 && y yy && posX < yy*2) gluk = 2;
- else if (posX > yy*2 && posX < grid.width) gluk = 3;
- else if ((posX > (yy+yy/2)) && posY < (grid.height/2)) gluk = 0;
+ if (posX < yy) gluk = glukmode[1];
+ else if(posX > yy && posX < yy*2) gluk = glukmode[2];
+ else if (posX > yy*2 && posX < grid.width) gluk = glukmode[3];
+ else if ((posX > (yy+yy/2)) && posY < (grid.height/2)) gluk = glukmode[0];
- for (int x = 0; x < w; x+=1) {
+ for (int x = 0; x < w; x+=glukstep[gluk]) {
//calculate ray position and direction
double cameraX = 2 * x / (double) w - 1; //x-coordinate in camera space
double rayPosX = posX;
@@ -149,14 +161,13 @@ public class RayCanvas extends Canvas {// implements Runnable {
int drawEnd = lineHeight / 2 + h / 2;
if (drawEnd >= h) drawEnd = h - 1;
- g.drawImage(pr, w / 2, h / 2, 3);
//choose wall color
int color = 0;
try {
color = colors[gluk][getCell(mapX, mapY)];
//give x and y sides different brightness
- if (side == 1) color -= 0x333333;
+ if (side == 1) color /= 2;
} catch (Exception e) {
color = 0xcccc44;
}
@@ -168,8 +179,8 @@ public class RayCanvas extends Canvas {// implements Runnable {
}
//speed modifiers
- double moveSpeed = (((double) dTime) / 1000) * 5.0; //the constant value is in squares/second
- double rotSpeed = (((double) dTime) / 1000) * 3.0; //the constant value is in radians/second
+ double moveSpeed = dTime * 5.0; //the constant value is in squares/second
+ double rotSpeed = dTime * 3.0; //the constant value is in radians/second
//move forward if no wall in front of you
if (keyb.getKeyState(UP)) {
@@ -179,9 +190,8 @@ public class RayCanvas extends Canvas {// implements Runnable {
if (getCell((int) posX, (int) (posY + dirY * moveSpeed)) == 0) {
posY += dirY * moveSpeed;
}
- }
- //move backwards if no wall behind you
- if (keyb.getKeyState(DOWN)) {
+ }else
+ if (keyb.getKeyState(DOWN)) {//move backwards if no wall behind you
if (getCell((int) (posX - dirX * moveSpeed), (int) posY) == 0) {
posX -= dirX * moveSpeed;
}
@@ -189,8 +199,14 @@ public class RayCanvas extends Canvas {// implements Runnable {
posY -= dirY * moveSpeed;
}
}
+ boolean isRight = keyb.getKeyState(RIGHT);
+ boolean isLeft = keyb.getKeyState(LEFT);
+ if(glukmode[0]==3 && gluk==3) {
+ if(isRight) {isRight = false; isLeft = true;}
+ else if(isLeft) {isLeft = false; isRight = true;}
+ }
//rotate to the right
- if (keyb.getKeyState(RIGHT)) {
+ if (isRight) {
//both camera direction and camera plane must be rotated
double oldDirX = dirX;
dirX = dirX * Math.cos(-rotSpeed) - dirY * Math.sin(-rotSpeed);
@@ -198,9 +214,8 @@ public class RayCanvas extends Canvas {// implements Runnable {
double oldPlaneX = planeX;
planeX = planeX * Math.cos(-rotSpeed) - planeY * Math.sin(-rotSpeed);
planeY = oldPlaneX * Math.sin(-rotSpeed) + planeY * Math.cos(-rotSpeed);
- }
- //rotate to the left
- if (keyb.getKeyState(LEFT)) {
+ }else
+ if (isLeft) {//rotate to the left
//both camera direction and camera plane must be rotated
double oldDirX = dirX;
dirX = dirX * Math.cos(rotSpeed) - dirY * Math.sin(rotSpeed);
@@ -210,6 +225,7 @@ public class RayCanvas extends Canvas {// implements Runnable {
planeY = oldPlaneX * Math.sin(rotSpeed) + planeY * Math.cos(rotSpeed);
}
+ g.drawImage(pr, w / 2, h / 2, 3);
if(showUI) showLabirinth(g, (int)posX, (int)posY);
if (end) {
g.setColor(0xFF6159);
@@ -246,6 +262,15 @@ public class RayCanvas extends Canvas {// implements Runnable {
end = false;
posX = 1;
posY = 1.1;
+ for(int i=0; i10) size = 10;
}
+
+ protected void pointerPressed(int x, int y) {
+ int w3 = w/3;
+ int h3 = h/3;
+ if(yw3 && x<(w-w3))) keyPressed(UP);
+ else if(y>(h-h3) && (x>w3 && x<(w-w3))) keyPressed(DOWN);
+
+ if(xh3 && y<(h-h3))) keyPressed(LEFT);
+ else if(x>(w-w3) && (y>h3 && y<(h-h3))) keyPressed(RIGHT);
+
+ if(x(w-w3) && y(h-h3)) keyPressed(-6);
+ else if(x>(w-w3) && y>(h-h3)) keyPressed(-7);
+ else if( (x>w3 && x<(w-w3)) && (y>h3 && y<(h-h3)) ) keyPressed(FIRE);
+ }
+
+ protected void pointerReleased(int x, int y) {
+ int w3 = w/3;
+ int h3 = h/3;
+ if(yw3 && x<(w-w3))) keyReleased(UP);
+ else if(y>(h-h3) && (x>w3 && x<(w-w3))) keyReleased(DOWN);
+
+ if(xh3 && y<(h-h3))) keyReleased(LEFT);
+ else if(x>(w-w3) && (y>h3 && y<(h-h3))) keyReleased(RIGHT);
+ }
}
diff --git a/src/about.ru b/src/about.ru
new file mode 100644
index 0000000..b94bdcb
--- /dev/null
+++ b/src/about.ru
@@ -0,0 +1,25 @@
+RayCanvas
+
+Цель игры - пройти лабиринт. Цвета стен, лабиринт и эффекты генерируются случайно.
+
+Управление в игре:
+Левый софт - сгенерировать новый лабиринт
+Правый софт - сгенерировать новый лабиринт с другим размером
+* - Показать карту
+1,3 (при показе карты) - изменить размер ячеек карты
+0 - выйти в меню
+Также есть поддержка TouchScreen.
+
+Копирайты:
+Алгоритм построения лабиринта - Carol Hamer,
+RayCasting C++ - http://www.student.kuleuven.be/~m0216922/CG/raycasting.html
+
+Понравилась игра? Поддержи автора.
+Web-Money:
+R812612235196
+Z155872305615
+U217957409638
+
+aNNiMON (Melnik Software)
+22.01.2011
+http://annimon.com/
\ No newline at end of file
diff --git a/src/com/emos/ui/ECanvas.java b/src/com/emos/ui/ECanvas.java
new file mode 100644
index 0000000..ca34803
--- /dev/null
+++ b/src/com/emos/ui/ECanvas.java
@@ -0,0 +1,50 @@
+/*
+ * aNNiMON 2011
+ * For more info visit http://annimon.com/
+ */
+
+package com.emos.ui;
+
+import javax.microedition.lcdui.Canvas;
+
+/**
+ * Расширенный класс Canvas
+ * @author aNNiMON
+ */
+public abstract class ECanvas extends Canvas {
+
+ public final int //константы клавиш
+ KEY_LSK = -6, //левый софт
+ KEY_RSK = -7; //правый софт
+ public final byte
+ PRESSED = 0,
+ REPEATED = 1,
+ RELEASED = 2;
+
+ public int w,h;
+
+ public ECanvas() {
+ setFullScreenMode(true);
+ w = getWidth();
+ h = getHeight();
+ }
+
+ public void keyPressed(int key) {
+ keyEvent(key, PRESSED);
+ }
+
+ public void keyRepeated(int key) {
+ keyEvent(key, REPEATED);
+ }
+
+ public void keyReleased(int key) {
+ keyEvent(key, RELEASED);
+ }
+
+ /**
+ * Обработчик клавиатуры
+ * @param key - код клавиши
+ * @param state - состояние клавиши (нажата, отпущена, зажата)
+ */
+ public abstract void keyEvent(int key, byte state);
+}
diff --git a/src/com/emos/ui/EConst.java b/src/com/emos/ui/EConst.java
new file mode 100644
index 0000000..6536dd4
--- /dev/null
+++ b/src/com/emos/ui/EConst.java
@@ -0,0 +1,20 @@
+/*
+ * aNNiMON 2011
+ * For more info visit http://annimon.com/
+ */
+
+package com.emos.ui;
+
+import javax.microedition.lcdui.Font;
+
+/**
+ *
+ * @author aNNiMON
+ */
+public class EConst {
+
+ public static final Font
+ titleFont = Font.getFont(Font.FACE_SYSTEM, Font.STYLE_PLAIN, Font.SIZE_LARGE),
+ mainFont = Font.getFont(Font.FACE_SYSTEM, Font.STYLE_PLAIN, Font.SIZE_MEDIUM);
+
+}
diff --git a/src/com/emos/ui/ESkin.java b/src/com/emos/ui/ESkin.java
new file mode 100644
index 0000000..896393b
--- /dev/null
+++ b/src/com/emos/ui/ESkin.java
@@ -0,0 +1,167 @@
+/*
+ * aNNiMON 2011
+ * For more info visit http://annimon.com/
+ */
+
+package com.emos.ui;
+
+import javax.microedition.lcdui.Graphics;
+
+/**
+ *
+ * @author aNNiMON
+ */
+public class ESkin {
+
+ public static int
+ wBack = 0xBF610151, //фон окна (каёмки)
+ wBack2 = 0xBF7D0169, //фон заливки фигур каёмки
+ wTitle = 0xFF84C1, //цвет заголовка окна
+ lBack = 0xE81E1E1E, //фон рабочей области
+
+ bg = 0; //фон
+
+ public ESkin(int skin) {
+ bg = 0;
+ lBack = 0xE81E1E1E;
+ wBack = 0xBF610151;
+ if(skin!=0) { //ставим яркость
+ wTitle = changeHSV(wBack, 0, 20);
+ wTitle = changeHSV(wBack, 1, -0.50f);
+ wTitle = changeHSV(wBack, 2, 0.60f);//(h+20, s-50, v+62 (100))
+ wBack2 = changeHSV(wBack, 2, -0.1f);
+ for(int i=0; i<=2; i++) {
+ float delta = getHSV(skin, i) - getHSV(wBack, i);
+ if(delta>-0.05 && delta<0.05) continue;
+ wTitle = changeHSV(wTitle, i, delta);
+ wBack2 = changeHSV(wBack2, i, delta);
+ }
+ wBack = skin;
+ }else{
+ wBack2 = 0xBF7D0169;
+ wTitle = 0xFF84C1;
+ }
+
+ }
+
+ private static int changeHSV(int color, int c, float value) {//0-h, 1-s, 2-v
+ float[] hsb = new float[3];
+ int qa = (color >> 24) & 0xff;
+ int qr = (color >> 16) & 0xff;
+ int qg = (color >> 8) & 0xff;
+ int qb = color & 0xff;
+ hsb = RGBtoHSV(qr, qg, qb, hsb);
+ hsb[c]+=value;
+ if(c==0) while(hsb[0]>360) hsb[0]-=360;
+ else {
+ if(hsb[c]>1.0) hsb[c]=hsb[c]-1.0f;
+ else if(hsb[c]<0) hsb[c]=-hsb[c];
+ }
+ return (qa << 24) | HSVtoRGB(hsb[0], hsb[1], hsb[2]);
+ }
+
+ private static int HSVtoRGB(float h, float s, float v) {
+ float qr = 0, qg = 0, qb = 0;
+ int r = 0, g = 0, b = 0;
+ if(s==0.0 && h==-1.0) return ((int)v << 16) | ((int)v << 8) | (int)v;
+ int Hi = (int) ((h / 60) % 6);
+ float f = (float) (h / 60 - (float)Math.floor(h/60));
+ float p = (float) ((float)v*(1.0f - (float)s));
+ float q = (float) ((float)v*(1.0f - (float)f*(float)s));
+ float t = (float) ((float)v*(1.0f - (s*(1.0-f))));
+ switch(Hi) {
+ case 0: qr = v; qg = t; qb = p; break;
+ case 1: qr = q; qg = v; qb = p; break;
+ case 2: qr = p; qg = v; qb = t; break;
+ case 3: qr = p; qg = q; qb = v; break;
+ case 4: qr = t; qg = p; qb = v; break;
+ case 5: qr = v; qg = p; qb = q; break;
+ }
+ r = (int) (255 * qr); g = (int) (255 * qg); b = (int) (255 * qb);
+ return (r << 16) | (g << 8) | b;
+ }
+
+ private static float[] RGBtoHSV(int qr, int qg, int qb, float[] hsv) {
+ float h = 0, s, v;
+ if (hsv == null) {
+ hsv = new float[3];
+ }
+ float r = (float) qr/255; float g = (float) qg/255; float b = (float) qb/255;
+ v = (r > g) ? r : g;
+ if (b > v) v = b;
+ float min = (r < g) ? r : g;
+ if (b < min) min = b;
+ // hue
+ if(v==min) h=0;
+ if(v==r && g>=b) h = 60 * ((g-b)/(v-min));
+ if(v==r && g> 16) & 0xff;
+ int qg = (color >> 8) & 0xff;
+ int qb = color & 0xff;
+ hsb = RGBtoHSV(qr, qg, qb, hsb);
+ return hsb[c];
+ }
+
+ public static void drawVGradient (Graphics gr, int rgb1, int rgb2, int xn, int yn, int wdh, int hgt) {
+ int r,g,b;
+ int r1, r2, g1, g2, b1, b2;
+ r1=acolor(rgb1, 'r'); r2=acolor(rgb2, 'r');
+ g1=acolor(rgb1, 'g'); g2=acolor(rgb2, 'g');
+ b1=acolor(rgb1, 'b'); b2=acolor(rgb2, 'b');
+ wdh+=xn;
+ hgt+=yn;
+ for (int i=yn; i255) r=255;
+ else if(r<0) r=0;
+ if(g>255) g=255;
+ else if(g<0) g=0;
+ if(b>255) b=255;
+ else if(b<0) b=0;
+ gr.setColor (r,g,b);
+ gr.drawLine (i,yn,i,hgt-1);
+ }
+ }
+
+ private static int acolor(int argb, char c) {
+ int bitmask = 0;
+ if(c=='b') return (argb & 0xff);
+ else if(c=='a') bitmask = 24;
+ else if(c=='r') bitmask = 16;
+ else if(c=='g') bitmask = 8;
+ return ((argb >> bitmask) & 0xff);
+ }
+}
diff --git a/src/com/emos/ui/EWindow.java b/src/com/emos/ui/EWindow.java
new file mode 100644
index 0000000..8751cef
--- /dev/null
+++ b/src/com/emos/ui/EWindow.java
@@ -0,0 +1,64 @@
+/*
+ * aNNiMON 2011
+ * For more info visit http://annimon.com/
+ */
+
+package com.emos.ui;
+
+import javax.microedition.lcdui.Graphics;
+
+/**
+ * Класс окна EmOS
+ * @author aNNiMON
+ */
+public abstract class EWindow extends ECanvas {
+
+ private String title;
+ private int fh,fw;
+ private final int otst = 5;
+ protected int ww,hh; //размеры рабочей области
+
+ public EWindow(String title) {
+ super();
+ this.title = title;
+ fw = EConst.titleFont.stringWidth(title)+title.length();
+ fh = EConst.titleFont.getHeight();
+ ww = w-otst*2;
+ hh = h-fh-otst*2;
+ }
+
+ public void paint(Graphics g) {
+ //Рисуем задний фон
+ g.setColor(ESkin.bg);
+ g.fillRect(0, 0, w, h);
+ //Рисуем фон окна (каёмки)
+ g.setColor(ESkin.wBack);
+ g.fillRoundRect(0, otst, w, h-otst, 5, 5);
+ g.setColor(ESkin.wBack2);
+ g.fillRoundRect(w/2-fw/2, 0, fw, fh, 5, 5);
+ //Рисуем текст заголовка
+ g.setFont(EConst.titleFont);
+ g.setColor(ESkin.wTitle);
+ g.drawString(title, w/2, 0, 17);
+ //Рисуем фон рабочей области
+ g.setClip(otst, fh+otst, ww, hh);
+ g.setColor(ESkin.lBack);
+ g.translate(otst, fh+otst);
+ g.fillRect(0, 0, ww, hh);
+ paint(g, ww, hh);
+ }
+
+ //Перерисовка рабочей области окна
+ protected void redraw() {
+ repaint(otst, fh+otst, ww, hh);
+ }
+
+ /**
+ * Метод отрисовки рабочей области окна
+ * @param g - Graphics
+ * @param w - ширина рабочей области
+ * @param h - высота рабочей области
+ */
+ public abstract void paint(Graphics g, int w, int h);
+
+}
diff --git a/src/com/emos/ui/StringEncoder.java b/src/com/emos/ui/StringEncoder.java
new file mode 100644
index 0000000..c0eae94
--- /dev/null
+++ b/src/com/emos/ui/StringEncoder.java
@@ -0,0 +1,58 @@
+package com.emos.ui;
+
+
+
+public class StringEncoder
+{
+ protected static char cp1251 [] =
+ {
+ '\u0410', '\u0411', '\u0412', '\u0413', '\u0414', '\u0415', '\u0416',
+ '\u0417', '\u0418', '\u0419', '\u041A', '\u041B', '\u041C', '\u041D',
+ '\u041E', '\u041F', '\u0420', '\u0421', '\u0422', '\u0423', '\u0424',
+ '\u0425', '\u0426', '\u0427', '\u0428', '\u0429', '\u042A', '\u042B',
+ '\u042C', '\u042D', '\u042E', '\u042F', '\u0430', '\u0431', '\u0432',
+ '\u0433', '\u0434', '\u0435', '\u0436', '\u0437', '\u0438', '\u0439',
+ '\u043A', '\u043B', '\u043C', '\u043D', '\u043E', '\u043F', '\u0440',
+ '\u0441', '\u0442', '\u0443', '\u0444', '\u0445', '\u0446', '\u0447',
+ '\u0448', '\u0449', '\u044A', '\u044B', '\u044C', '\u044D', '\u044E',
+ '\u044F'
+ };
+
+ public static char decodeCharCP1251 (byte b)
+ {
+ int ich = b & 0xff;
+ if (ich == 0xb8)
+ return 0x0451;
+ else if (ich == 0xa8)
+ return 0x0401;
+ else if (ich >= 0xc0)
+ return cp1251[ich-192];
+ return (char)ich;
+ }
+
+ public static byte encodeCharCP1251 (char ch)
+ {
+ if (ch > 0 && ch < 128)
+ return (byte) ch;
+ else if (ch == 0x401)
+ return -88; //
+ else if (ch == 0x404)
+ return -86; //
+ else if (ch == 0x407)
+ return -81; //
+ else if (ch == 0x451)
+ return -72; //
+ else if (ch == 0x454)
+ return -70; //
+ else if (ch == 0x457)
+ return -65; //
+ return (byte)((byte)(ch) + 176);
+ }
+
+ public static char checkCP1251 (char ch)
+ {
+ int bt = (byte) ch;
+ if(bt < 0) return decodeCharCP1251((byte) (256 + bt));
+ else return ch;
+ }
+}