This commit is contained in:
Victor 2018-11-15 00:06:29 +02:00
commit 67a3be6fcb
33 changed files with 3678 additions and 0 deletions

83
build.xml Normal file
View File

@ -0,0 +1,83 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- You may freely edit this file. See commented blocks below for -->
<!-- some examples of how to customize the build. -->
<!-- (If you delete it and reopen the project it will be recreated.) -->
<project name="S3DGame" default="jar" basedir=".">
<description>Builds, tests, and runs the project .</description>
<import file="nbproject/build-impl.xml"/>
<!--
There exist several targets which are by default empty and which can be
used for execution of your tasks. These targets are usually executed
before and after some main targets. They are:
pre-init: called before initialization of project properties
post-init: called after initialization of project properties
pre-preprocess: called before text preprocessing of sources
post-preprocess: called after text preprocessing of sources
pre-compile: called before source compilation
post-compile: called after source compilation
pre-obfuscate: called before obfuscation
post-obfuscate: called after obfuscation
pre-preverify: called before preverification
post-preverify: called after preverification
pre-jar: called before jar building
post-jar: called after jar building
pre-build: called before final distribution building
post-build: called after final distribution building
pre-clean: called before cleaning build products
post-clean: called after cleaning build products
Example of pluging a my-special-task after the compilation could look like
<target name="post-compile">
<my-special-task>
<fileset dir="${build.classes.dir}"/>
</my-special-task>
</target>
For list of available properties check the imported
nbproject/build-impl.xml file.
Other way how to customize the build is by overriding existing main targets.
The target of interest are:
preprocess: preprocessing
extract-libs: extraction of libraries and resources
compile: compilation
create-jad: construction of jad and jar manifest source
obfuscate: obfuscation
preverify: preverification
jar: jar archive building
run: execution
debug: execution in debug mode
build: building of the final distribution
javadoc: javadoc generation
Example of overriding the target for project execution could look like
<target name="run" depends="init,jar">
<my-special-exec jadfile="${dist.dir}/${dist.jad}"/>
</target>
Be careful about correct dependencies when overriding original target.
Again, for list of available properties which you can use check the target
you are overriding in nbproject/build-impl.xml file.
A special target for-all-configs can be used to run some specific targets for
all project configurations in a sequence. File nbproject/build-impl.xml
already contains some "for-all" targets:
jar-all
javadoc-all
clean-all
Example of definition of target iterating over all project configurations:
<target name="jar-all">
<property name="target.to.call" value="jar"/>
<antcall target="for-all-configs"/>
</target>
-->
</project>

1247
nbproject/build-impl.xml Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,8 @@
# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml.
# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you.
build.xml.data.CRC32=0e3f44a9
build.xml.script.CRC32=94773986
build.xml.stylesheet.CRC32=9c6a911d
nbproject/build-impl.xml.data.CRC32=0e3f44a9
nbproject/build-impl.xml.script.CRC32=1a4b0164
nbproject/build-impl.xml.stylesheet.CRC32=e46c2d22

View File

@ -0,0 +1,7 @@
#Sun, 25 Mar 2012 12:33:16 +0200
app-version.autoincrement=true
config.active=
deployment.counter=51
deployment.number=0.0.50
javadoc.preview=true
netbeans.user=C\:\\Users\\aNNiMON\\.netbeans\\7.1

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<project-private xmlns="http://www.netbeans.org/ns/project-private/1">
<editor-bookmarks xmlns="http://www.netbeans.org/ns/editor-bookmarks/1"/>
</project-private>

View File

@ -0,0 +1,105 @@
abilities=MMAPI=1.1,SATSAJCRMI=1.0,SATSACRYPTO=1.0,JSR82=1.1,NOKIAUI=1.0,JSR226=1.0,capuchin=1.0,MIDP=2.1,JSR229=1.1.0,SATSAAPDU=1.0,CLDC=1.1,JSR177=1.0,JSR179=1.0.1,eSWT=1.1,J2MEWS=1.0,VSCL=2.1,WMA=2.0,JSR172=1.0,JSR256=1.1,SEMC_EXT_JP8=1.0,ColorScreen,NokiaUI=1.0,OBEX=1.0,JSR238=1.0,JSR239=1.0,JSR211=1.0,JSR234=1.0,ScreenWidth=240,MascotV3=1.0,JSR75=1.0,IAPInfo=1.0,SATSAPKI=1.0,JSR184=1.1,ScreenHeight=321,ScreenColorDepth=8,JSR180=1.0.1,J2MEXMLRPC=1.0,
all.configurations=\
application.args=
application.description=
application.description.detail=
application.name=
application.vendor=Vendor
build.classes.dir=${build.dir}/compiled
build.classes.excludes=**/*.java,**/*.form,**/*.class,**/.nbintdb,**/*.mvd,**/*.wsclient,**/*.vmd
build.dir=build/${config.active}
build.root.dir=build
debug.level=debug
debugger.timeout=
deployment.copy.target=deploy
deployment.instance=default
deployment.jarurl=${dist.jar}
deployment.method=NONE
deployment.override.jarurl=false
dist.dir=dist/${config.active}
dist.jad=Flood-It.jad
dist.jar=Flood-It.jar
dist.javadoc.dir=${dist.dir}/doc
dist.root.dir=dist
extra.classpath=
filter.exclude.tests=false
filter.excludes=
filter.more.excludes=**/overview.html,**/package.html
filter.use.standard=true
jar.compress=true
javac.debug=true
javac.deprecation=false
javac.encoding=UTF-8
javac.optimize=false
javac.source=1.3
javac.target=1.3
javadoc.author=false
javadoc.encoding=
javadoc.noindex=false
javadoc.nonavbar=false
javadoc.notree=false
javadoc.private=false
javadoc.splitindex=true
javadoc.use=true
javadoc.version=false
javadoc.windowtitle=
libs.classpath=
main.class=
main.class.class=applet
manifest.apipermissions=
manifest.file=manifest.mf
manifest.is.liblet=false
manifest.jad=
manifest.manifest=
manifest.midlets=MIDlet-1: Flood-It,/icon.png,Main\n
manifest.others=MIDlet-Vendor: aNNiMON\nMIDlet-Name: Flood-It\nMIDlet-Version: 1.0.1\n
manifest.pushregistry=
name=S3DGame
no.dependencies=false
nokiaS80.application.icon=
obfuscated.classes.dir=${build.dir}/obfuscated
obfuscation.custom=@E:\\SETUPS\\Disk\\Programming\\Java\\annimon.pro
obfuscation.level=1
obfuscator.destjar=${build.dir}/obfuscated.jar
obfuscator.srcjar=${build.dir}/before-obfuscation.jar
platform.active=Sony_Ericsson_SDK_2_5_0_6_for_the_Java_TM__ME_Platform_Emulator_
platform.active.description=Sony Ericsson SDK 2.5.0.6 for the Java(TM) ME Platform(Emulator)
platform.apis=WMA-2.0,JSR211-1.0,JSR82-1.1,JSR177-1.0,JSR234-1.0,SATSA-APDU-1.0,capuchin-1.0,J2ME-WS-1.0,J2ME-XMLRPC-1.0,SATSA-JCRMI-1.0,SATSA-CRYPTO-1.0,JSR239-1.0,MascotV3-1.0,JSR238-1.0,MMAPI-1.1,JSR256-1.1,NokiaUI-1.0,IAPInfo-1.0,JSR229-1.1.0,SATSA-PKI-1.0,JSR180-1.0.1,JSR226-1.0,SEMC_EXT_JP8-1.0,VSCL-2.0,VSCL-2.1,eSWT-1.1,JSR75-1.0,JSR184-1.1,JSR179-1.0.1
platform.bootclasspath=${platform.home}/lib/eswt.jar:${platform.home}/lib/mascotv3.jar:${platform.home}/lib/jsr226.jar:${platform.home}/lib/jsr256.jar:${platform.home}/lib/satsa-crypto.jar:${platform.home}/lib/jsr229.jar:${platform.home}/lib/jsr238.jar:${platform.home}/lib/j2me-xmlrpc.jar:${platform.home}/lib/jsr211.jar:${platform.home}/lib/vscl21.jar:${platform.home}/lib/satsa-jcrmi.jar:${platform.home}/lib/jsr082.jar:${platform.home}/lib/satsa-apdu.jar:${platform.home}/lib/jsr184.jar:${platform.home}/lib/nokiaext.jar:${platform.home}/lib/capuchin.jar:${platform.home}/lib/jsr239.jar:${platform.home}/lib/jsr75.jar:${platform.home}/lib/satsa-pki.jar:${platform.home}/lib/jsr179.jar:${platform.home}/lib/jsr180.jar:${platform.home}/lib/iapinfo.jar:${platform.home}/lib/vscl.jar:${platform.home}/lib/mmapi.jar:${platform.home}/lib/j2me-ws.jar:${platform.home}/lib/wma20.jar:${platform.home}/lib/jsr234.jar:${platform.home}/lib/semc_ext_jp8.jar:${platform.home}/lib/cldcapi11.jar:${platform.home}/lib/midpapi20.jar
platform.configuration=CLDC-1.1
platform.device=SonyEricsson_JP8_240x320_Emu
platform.fat.jar=true
platform.profile=MIDP-2.0
platform.trigger=CLDC
platform.type=UEI-1.0.1
preprocessed.dir=${build.dir}/preprocessed
preverify.classes.dir=${build.dir}/preverified
preverify.sources.dir=${build.dir}/preverifysrc
resources.dir=resources
run.cmd.options=
run.jvmargs=
run.method=STANDARD
run.security.domain=trusted
run.use.security.domain=false
savaje.application.icon=
savaje.application.icon.focused=
savaje.application.icon.small=
savaje.application.uid=TBD
savaje.bundle.base=
savaje.bundle.debug=false
savaje.bundle.debug.port=
semc.application.caps=
semc.application.icon=
semc.application.icon.count=
semc.application.icon.splash=
semc.application.icon.splash.installonly=false
semc.application.uid=E1760129
semc.certificate.path=
semc.private.key.password=
semc.private.key.path=
sign.alias=
sign.enabled=false
sign.keystore=
src.dir=src
use.emptyapis=true
use.preprocessor=true

10
nbproject/project.xml Normal file
View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://www.netbeans.org/ns/project/1">
<type>org.netbeans.modules.kjava.j2meproject</type>
<configuration>
<data xmlns="http://www.netbeans.org/ns/j2me-project">
<name>S3DGame</name>
<minimum-ant-version>1.6</minimum-ant-version>
</data>
</configuration>
</project>

207
src/About.java Normal file
View File

@ -0,0 +1,207 @@
/*
* aNNiMON 2010
* For more info visit http://annimon.com/
*/
/*
* На основе класса MultiLineText от А.С. Ледкова
* www.mobilab.ru
*/
import java.util.Vector;
import javax.microedition.lcdui.Canvas;
import javax.microedition.lcdui.Font;
import javax.microedition.lcdui.Graphics;
import javax.microedition.lcdui.Image;
public class About extends Canvas {
/* Фон */
private Image background;
/* Шрифт */
private Font def;
/* Размер шрифта */
private int defHeight;
/* Максимальная высота выводимого текста */
private int maxHeight;
/* Высота, с которой будет отрисовываться текст */
private int minHeight;
/* Шаг при прокрутке текста */
private int stepY;
/* Массив строк */
private Vector strLines;
/* Текущая высота текста */
private int textHeight;
/* Размер экрана */
private int w, h;
public About(String path) {
setFullScreenMode(true);
w = getWidth();
h = getHeight();
def = Font.getDefaultFont();
stepY = defHeight = def.getHeight() + 2;
maxHeight = h - defHeight - 1;
initParameters(path);
}
public void setBackground(Image image) {
background = Util.smooth(image, 5, 5);
}
protected void paint(Graphics g) {
g.drawImage(background, 0, 0, Graphics.LEFT | Graphics.TOP);
g.setFont(def);
g.setColor(0xFFFFFF);
g.drawString("Flood-It", w / 2, 1, 17);
g.setClip(0, defHeight + 1, w, maxHeight);
int y1 = minHeight;
for (int i = 0; i < strLines.size(); i++) {
if ((y1 + defHeight) > 0) {
g.drawString(strLines.elementAt(i).toString(), 1, defHeight + 5 + y1, Graphics.LEFT | Graphics.TOP);
}
y1 = y1 + defHeight;
if (y1 > maxHeight) {
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) || (key == KEY_STAR)) {
Menu.showMenu();
}
repaint();
}
/**
* Расчет параметров
*/
private void initParameters(String path) {
// Разбиваем строку на массив строк
strLines = new Vector();
String str = Util.getText(path, true);
String[] arr = Util.splitString(str, "\n");
for (int i = 0; i < arr.length; i++) {
String substr = arr[i];
int i0 = 0,
in = 0,
jw = 0; // Смещение от начала строки
int imax = substr.length(); // Длина строки
boolean isexit = true;
minHeight = 0;
while (isexit) {
int space = substr.indexOf(" ", i0 + 1);
if (space <= i0) {
space = imax;
isexit = false;
}
int j = def.stringWidth(substr.substring(i0, space));
if (jw + j < w) { // Слово вмещается
jw = jw + j;
i0 = space;
} else { // Слово не вмещается
strLines.addElement(substr.substring(in, i0));
in = i0 + 1;
jw = j;
if (j > 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 void moveDown() {
if (textHeight > maxHeight) {
minHeight = minHeight - stepY;
if (maxHeight - minHeight > textHeight) {
minHeight = maxHeight - textHeight;
}
}
}
private void moveUp() {
if (textHeight > maxHeight) {
minHeight = minHeight + stepY;
if (minHeight > 0) {
minHeight = 0;
}
}
}
private void pageUp() {
if (textHeight > maxHeight) {
minHeight = minHeight + maxHeight;
if (minHeight > 0) {
minHeight = 0;
}
}
}
private void pageDown() {
if (textHeight > maxHeight) {
minHeight = minHeight - maxHeight;
if (maxHeight - minHeight > textHeight) {
minHeight = maxHeight - textHeight;
}
}
}
}

87
src/Box.java Normal file
View File

@ -0,0 +1,87 @@
import com.s3d.Mesh;
import com.s3d.Square;
import com.s3d.Vertex;
/*
* aNNiMON 2012
* For more info visit http://annimon.com/
*/
/**
* Создаёт кубик из поверхностей.
* @author aNNiMON
*/
public class Box {
private Vertex[][] box;
private int size;
public Box(int size) {
this.size = size;
box = new Vertex[6][];
setVertexes();
}
public Mesh getBox(int color) {
Mesh mesh = new Mesh();
for (int i = 0; i < box.length; i++) {
mesh.addFace(new Square(box[i][0], box[i][1], box[i][2], box[i][3], color));
}
return mesh;
}
private void setVertexes() {
int i = size / 2;
// Низ
box[0] = new Vertex[] {
new Vertex(-i, -i, -i),
new Vertex(-i, -i, i),
new Vertex(i, -i, i),
new Vertex(i, -i, -i)
};
// Верх
box[1] = new Vertex[] {
new Vertex(-i, i, -i),
new Vertex(-i, i, i),
new Vertex(i, i, i),
new Vertex(i, i, -i)
};
// Фронт
box[2] = new Vertex[] {
new Vertex(i, -i, i),
new Vertex(-i, -i, i),
new Vertex(-i, i, i),
new Vertex(i, i, i)
};
// Бэк
box[3] = new Vertex[] {
new Vertex(-i, -i, -i),
new Vertex(i, -i, -i),
new Vertex(i, i, -i),
new Vertex(-i, i, -i)
};
// Лево
box[4] = new Vertex[] {
new Vertex(-i, -i, -i),
new Vertex(-i, -i, i),
new Vertex(-i, i, i),
new Vertex(-i, i, -i)
};
// Право
box[5] = new Vertex[] {
new Vertex(i, -i, -i),
new Vertex(i, -i, i),
new Vertex(i, i, i),
new Vertex(i, i, -i)
};
}
}

284
src/Canv.java Normal file
View File

@ -0,0 +1,284 @@
/*
* aNNiMON 2012
* For more info visit http://annimon.com/
*/
import com.s3d.Matrix3D;
import com.s3d.Camera;
import javax.microedition.lcdui.Canvas;
import javax.microedition.lcdui.Graphics;
import javax.microedition.lcdui.Image;
/**
* @author aNNiMON
*/
public class Canv extends Canvas implements Runnable {
/* Размер шага при перемещении в пространстве */
private static final int STEP_SIZE = 5;
/* Режимы управления */
private static final byte
MODE_GAME = 0,
MODE_SET_POSITION = 1,
MODE_SET_ROTATION = 2;
/* Двойная буферизация */
private Graphics G;
private Image I;
/* Цвет заливки */
private byte fillId;
/* Игра */
public FloodIt game;
/* Матрица, необходимая для отрисовки модели */
private Matrix3D matrix;
/* Режим управления */
private int mode;
/* Положение в пространстве */
private int modelX, modelY, modelZ;
/* Углы поворота модели */
private int rotX, rotY, rotZ;
/* Софтбар заливаемых цветов */
private SoftBar soft;
/* Надпись в заголовке */
private String title;
/* Размер экрана */
private int w, h;
public Canv() {
setFullScreenMode(true);
w = getWidth();
h = getHeight();
I = Image.createImage(w, h);
G = I.getGraphics();
initCameraMatrix();
soft = new SoftBar();
// Режим управления
mode = MODE_GAME;
title = "Flood-It";
fillId = 0;
new Thread(this).start();
}
private void initCameraMatrix() {
// Установить параметры камеры
Camera.w = w;
Camera.h = h;
// Дальность рендеринга = 5000
Camera.limit = 5000;
game = new FloodIt(Rms.lastTableSize);
matrix = new Matrix3D();
// Углы поворота
rotX = 15;
rotY = -15;
rotZ = 0;
// Координаты
modelX = 5;
modelY = 40;
modelZ = 590 + (Rms.lastTableSize - 14) * 36;
conversions();
}
public void paintTableOptions(Graphics g, int tableSize) {
if (game.getTableSize() != tableSize) game.setTableSize(tableSize);
modelZ = 590 + (tableSize - 14) * 36;
conversions();
g.setGrayScale(250);
g.drawString(String.valueOf(tableSize), w / 2, 5, Graphics.TOP | Graphics.HCENTER);
game.paint(g, matrix);
}
public void paint(Graphics g) {
G.setColor(0x00);
G.fillRect(0, 0, w, h);
game.paint(G, matrix);
soft.paint(G, fillId);
G.setColor(0xFFFFFF);
G.drawString(title, w / 2, 0, Graphics.TOP | Graphics.HCENTER);
//
g.drawImage(I, 0, 0, Graphics.TOP | Graphics.LEFT);
}
/**
* Преобразования
*/
private void conversions() {
// Сбросываем настройки матрицы
matrix.unit();
// Поворачиваем по всем осям
matrix.xrot(rotY);
matrix.yrot(rotX);
matrix.zrot(rotZ);
// Устанавливаем координаты модели
matrix.translate(modelX, modelY, modelZ);
}
protected void sizeChanged(int w, int h) {
this.w = getWidth();
this.h = getHeight();
I = Image.createImage(w, h);
G = I.getGraphics();
super.sizeChanged(w, h);
}
protected void keyPressed(int key) {
int ga = getGameAction(key);
if (key == KEY_NUM0) {
nextMode();
return;
} else if ((key == -7) || (key == -6) || (key == KEY_STAR)) {
Menu.showMenu();
}
if (mode == MODE_GAME) {
if ( (key >= KEY_NUM1) && (key <= KEY_NUM6) ) {
fillId = (byte) (key - KEY_NUM1);
game.fill(fillId);
} else keyModeGame(ga, key);
} else if (mode == MODE_SET_POSITION) {
keyModeSetPosition(ga, key);
} else if (mode == MODE_SET_ROTATION) {
keyModeSetRotation(ga, key);
}
conversions();
repaint();
}
private void nextMode() {
mode++;
if (mode > MODE_SET_ROTATION) {
mode = MODE_GAME;
}
if (mode == MODE_GAME) {
title = "Flood-It";
} else if (mode == MODE_SET_POSITION) {
title = Language.getMessage(Language.POSITION);
} else if (mode == MODE_SET_ROTATION) {
title = Language.getMessage(Language.ROTATE);
}
}
private void keyModeSetRotation(int ga, int key) {
// Увеличиваем угол поворота
switch (ga) {
case LEFT:
rotX -= STEP_SIZE;
break;
case RIGHT:
rotX += STEP_SIZE;
break;
case UP:
rotY += STEP_SIZE;
break;
case DOWN:
rotY -= STEP_SIZE;
break;
default :
if (key == KEY_NUM1) rotZ += STEP_SIZE;
else if (key == KEY_NUM3) rotZ -= STEP_SIZE;
}
if (rotX > 360) rotX = 1;
if (rotY > 360) rotY = 1;
if (rotZ > 360) rotZ = 1;
}
private void keyModeSetPosition(int ga, int key) {
// Сдвигаем координаты модели
switch (ga) {
case LEFT:
modelX -= STEP_SIZE;
break;
case RIGHT:
modelX += STEP_SIZE;
break;
case UP:
modelY += STEP_SIZE;
break;
case DOWN :
modelY -= STEP_SIZE;
break;
default :
if (key == KEY_NUM1) modelZ += STEP_SIZE;
else if (key == KEY_NUM3) modelZ -= STEP_SIZE;
}
}
private void keyModeGame(int ga, int key) {
// Изменяем цвет заливки
switch (ga) {
case FIRE:
game.fill(fillId);
break;
case LEFT:
case UP:
fillId--;
if (fillId < 0) {
fillId = Main.MAX_COLORS - 1;
}
break;
case RIGHT:
case DOWN:
fillId++;
if (fillId >= Main.MAX_COLORS) {
fillId = 0;
}
break;
default:
if (key == KEY_POUND) {
game.reset();
}
}
/*
* По окончанию игры ставим курсор в -1, а если игра не закончилась
* но курсор по прежнему -1, то ставим его в 0
*/
if (game.checkTable()) fillId = -1;
else if (fillId == -1) fillId = 0;
}
protected void keyRepeated(int key) {
keyPressed(key);
}
public void run() {
while (true) {
repaint();
try {
Thread.sleep(5L);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
}
}

135
src/FloodIt.java Normal file
View File

@ -0,0 +1,135 @@
import com.s3d.Matrix3D;
import java.util.Random;
import javax.microedition.lcdui.Graphics;
/*
* aNNiMON 2012
* For more info visit http://annimon.com/
*/
/**
*
* @author aNNiMON
*/
public class FloodIt {
private int moves; // количество ходов
private byte prevColor;
private byte[][] table; // игровое поле
private Table table3d;
private int tableSize; // размер игрового поля
public FloodIt(int tableSize) {
setTableSize(tableSize);
}
public int getTableSize() {
return tableSize;
}
public final void setTableSize(int tableSize) {
this.tableSize = tableSize;
Rms.lastTableSize = tableSize;
table3d = new Table(tableSize);
moves = 0;
initTable();
prevColor = table[0][0];
}
public void reset() {
initTable();
}
public void fill(byte color) {
if (table == null) {
Main.midlet.hiscore.checkForHiscore(tableSize, moves);
initTable();
}
if ((color < 0) || (color >= Main.MAX_COLORS)) {
return;
}
// Закраска выбранным цветом
prevColor = table[0][0];
if (prevColor != color) {
fillTable(0, 0, color);
moves++;
}
table3d.updateTable(table);
}
public void paint(Graphics g, Matrix3D matrix) {
if (checkTable()) {
int w = g.getClipWidth();
int h = g.getClipHeight();
g.setColor(0xFFFFFF);
g.drawString(Language.getMessage(Language.GAME_OVER), w / 2, h / 2 - h / 16, Graphics.HCENTER | Graphics.BOTTOM);
String str = Language.getMessage(Language.MOVES) + String.valueOf(moves);// + " ходов";
g.drawString(str, w / 2, h / 2 + h / 16, Graphics.HCENTER | Graphics.TOP);
table = null;
return;
}
table3d.paint(g, matrix);
}
private void initTable() {
table = new byte[tableSize][tableSize];
moves = 0;
// Генерируем игровое поле
Random rnd = new Random();
for (int i = 0; i < tableSize; i++) {
for (int j = 0; j < tableSize; j++) {
table[i][j] = (byte) rnd.nextInt(Main.MAX_COLORS);
}
}
table3d.updateTable(table);
}
/* Заливка поля */
private void fillTable(int x, int y, byte color) {
// Проверка на выход за границы игрового поля
if ((x < 0) || (y < 0) || (x >= tableSize) || (y >= tableSize)) {
return;
}
if (table[x][y] == prevColor) {
table[x][y] = color;
// Заливаем смежные области
fillTable(x - 1, y, color);
fillTable(x + 1, y, color);
fillTable(x, y - 1, color);
fillTable(x, y + 1, color);
}
}
/* Проверка, залита ли вся область одним цветом */
public boolean checkTable() {
if (table == null) {
return true;
}
byte color = table[0][0];
for (int i = 0; i < tableSize; i++) {
for (int j = 0; j < tableSize; j++) {
if (table[i][j] != color) {
return false;
}
}
}
return true;
}
}

136
src/Hiscores.java Normal file
View File

@ -0,0 +1,136 @@
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import javax.microedition.lcdui.*;
/*
* aNNiMON 2012
* For more info visit http://annimon.com/
*/
/**
*
* @author aNNiMON
*/
public class Hiscores {
/** Сколько хранить результатов*/
private static final int MAX_STORE_SCORES = 5;
// Результаты
private int[][] scores;
private String[][] names;
public Hiscores() {
scores = new int[Main.MAX_TABLE_SIZE - Main.MIN_TABLE_SIZE + 1][MAX_STORE_SCORES];
names = new String[Main.MAX_TABLE_SIZE - Main.MIN_TABLE_SIZE + 1][MAX_STORE_SCORES];
if (Rms.firstStart) resetHiscores();
}
public final void resetHiscores() {
for (int i = 0; i < scores.length; i++) {
for (int j = 0; j < scores[0].length; j++) {
scores[i][j] = 999;
names[i][j] = "";
}
}
}
public void checkForHiscore(int tableSize, int newScore) {
int tableIndex = tableSize - Main.MIN_TABLE_SIZE;
if (newScore < scores[tableIndex][0]) {
askForFileName(tableIndex, newScore);
}
}
public void paintResults(Graphics g, int scoreTableSize) {
int tableIndex = scoreTableSize - Main.MIN_TABLE_SIZE;
int width = g.getClipWidth();
int height = g.getClipHeight();
int border = width / 16;
int step = height / 3 / MAX_STORE_SCORES;
int colorStep = 100 / MAX_STORE_SCORES;
int y = height - border - (MAX_STORE_SCORES+1)*step;
g.setGrayScale(250);
g.drawString(String.valueOf(scoreTableSize), width / 2, y, Graphics.BOTTOM | Graphics.HCENTER);
for (int i = 0; i < scores[tableIndex].length; i++) {
g.setGrayScale(150 + colorStep*i);
y = height - border - (/*MAX_STORE_SCORES-1-*/i)*step;
String name = names[tableIndex][i];
if (name.length() == 0) name = Language.getMessage(Language.UNKNOWN);
g.drawString(name, border, y, Graphics.BOTTOM | Graphics.LEFT);
g.drawString(String.valueOf(scores[tableIndex][i]), width-border, y, Graphics.BOTTOM | Graphics.RIGHT);
}
}
public void saveScores(DataOutputStream dos) throws IOException {
for (int i = 0; i < scores.length; i++) {
for (int j = 0; j < scores[0].length; j++) {
dos.writeInt(scores[i][j]);
dos.writeUTF(names[i][j]);
}
}
}
public void loadScores(DataInputStream dis) throws IOException {
for (int i = 0; i < scores.length; i++) {
for (int j = 0; j < scores[0].length; j++) {
scores[i][j] = dis.readInt();
names[i][j] = dis.readUTF();
}
}
}
private void askForFileName(final int tableIndex, final int newScore) {
final Displayable prevDisplayable = Main.midlet.dsp.getCurrent();
Form form = new Form(Language.getMessage(Language.NEW_HIGH_SCORE)+newScore);
final TextField nameTF = new TextField(Language.getMessage(Language.ENTER_YOUR_NAME), Rms.playerName, 12, TextField.ANY);
final Command ok = new Command(Language.getMessage(Language.OK), Command.OK, 1);
form.append(nameTF);
form.addCommand(ok);
form.setCommandListener(new CommandListener() {
public void commandAction(Command cmd, Displayable disp) {
if (cmd == ok) {
String text = nameTF.getString();
if (text.length() > 0) {
Rms.playerName = text;
scores[tableIndex][0] = newScore;
names[tableIndex][0] = text;
sortHiscore(tableIndex);
Main.midlet.dsp.setCurrent(prevDisplayable);
}
}
}
});
Main.midlet.dsp.setCurrent(form);
}
private void sortHiscore(int index) {
int[] sortArray = scores[index];
for (int i = 0; i < sortArray.length; i++) {
int max = i;
for (int j = i + 1; j < sortArray.length; j++) {
if (sortArray[j] > sortArray[max]) max = j;
}
int temp = sortArray[max];
sortArray[max] = sortArray[i];
sortArray[i] = temp;
String tmp = names[index][max];
names[index][max] = names[index][i];
names[index][i] = tmp;
}
scores[index] = sortArray;
}
}

72
src/Language.java Normal file
View File

@ -0,0 +1,72 @@
/*
* aNNiMON 2012
* For more info visit http://annimon.com/
*/
/**
* @author aNNiMON
*/
public class Language {
public static final byte
START = 0,
OPTIONS = 1,
HIGH_SCORE = 2,
HELP = 3,
EXIT = 4,
TABLE_SIZE = 5,
LANGUAGE = 6,
RESET_SCORES = 7,
BACK = 8,
POSITION = 9,
ROTATE = 10,
GAME_OVER = 11,
MOVES = 12,
NEW_HIGH_SCORE = 13,
ENTER_YOUR_NAME = 14,
OK = 15,
UNKNOWN = 16;
private static String[] langs = Util.getLanguages("langs.txt");
private static int currentLang = 0;
private static String[] str;
public static void nextLanguage() {
currentLang++;
if (currentLang >= langs.length) currentLang = 0;
loadLocale(langs[currentLang]);
}
public static String getCurrentLanguage() {
return langs[currentLang];
}
public static void detectLocale() {
String locale = System.getProperty("microedition.locale");
if ((locale != null) && (locale.length() > 1)) {
locale = locale.substring(0, 2).toLowerCase();
detectLang(locale);
}
}
private static void detectLang(String locale) {
for (int i = 0; i < langs.length; i++) {
if (locale.equals(langs[i])) currentLang = i;
}
}
public static String getMessage(int index) {
return str[index];
}
public static void loadLocale(String locale) {
Rms.language = locale;
detectLang(locale);
str = Util.splitString(Util.getText(locale+".lang", false), "\n");
}
}

55
src/Main.java Normal file
View File

@ -0,0 +1,55 @@
/*
* aNNiMON 2012
* For more info visit http://annimon.com/
*/
import javax.microedition.lcdui.Display;
import javax.microedition.midlet.MIDlet;
/**
* @author aNNiMON
*/
public class Main extends MIDlet {
public static final int MIN_TABLE_SIZE = 5;
public static final int MAX_TABLE_SIZE = 25;
public static final int BOX_SIZE = 30;
public static final int[] COLORS = {
0xE81C20, 0x20B048, 0x486CF0, 0xF8F000, 0xF87C00, 0x683098
};
public static final int MAX_COLORS = 6;// количество цветов
public static Main midlet;
public About about;
public Display dsp;
public Canv floodit;
public Hiscores hiscore;
public Menu menu;
public Main() {
midlet = Main.this;
dsp = Display.getDisplay(Main.this);
hiscore = new Hiscores();
Rms.restoreOptions();
if (Rms.firstStart) {
Language.detectLocale();
Rms.language = Language.getCurrentLanguage();
}
Language.loadLocale(Rms.language);
menu = new Menu();
floodit = new Canv();
about = new About("about."+Language.getCurrentLanguage());
}
public void startApp() {
dsp.setCurrent(menu);
}
public void pauseApp() {}
public void destroyApp(boolean ex) {
Rms.saveOptions();
notifyDestroyed();
}
}

326
src/Menu.java Normal file
View File

@ -0,0 +1,326 @@
/*
* aNNiMON 2012
* For more info visit http://annimon.com/
*/
import com.s3d.Matrix3D;
import com.s3d.Camera;
import javax.microedition.lcdui.Canvas;
import javax.microedition.lcdui.Font;
import javax.microedition.lcdui.Graphics;
import javax.microedition.lcdui.Image;
/**
* @author aNNiMON
*/
public class Menu extends Canvas implements Runnable {
private static final byte
MENU_MAIN = 0,
MENU_OPTIONS = 1,
ITEM_HIGHSCORES = 2,
ITEM_SET_SIZE = 3; // настройка размера поля
private static boolean threadRun;
/* Двойная буферизация */
private Graphics G;
private Image I;
/* Меню */
private byte activeMenu;
/* Шрифт меню */
private Font font;
private int fontHeight;
/* Матрица, необходимая для отрисовки текста */
private Matrix3D matrix;
private int[] menuCursor;
private String[][] menuItems;
/* Углы поворота модели */
private float rotY, rotZ;
/* Настройки */
private int tableSize;
/* Опции */
private int scoreTableSize;
/* Трёхмерный текст на фоне */
private Text3D text;
/* Размер экрана */
private int w, h;
public Menu() {
setFullScreenMode(true);
w = getWidth();
h = getHeight();
I = Image.createImage(w, h);
G = I.getGraphics();
// Шрифт
font = Font.getFont(Font.FACE_SYSTEM, Font.STYLE_PLAIN, Font.SIZE_MEDIUM);
fontHeight = font.getHeight() + 2;
// Меню
activeMenu = MENU_MAIN;
menuCursor = new int[2];
menuCursor[MENU_MAIN] = 0;
menuCursor[MENU_OPTIONS] = 0;
menuItems = new String[2][];
initMenuStrings();
// Углы поворота
rotY = 0;
rotZ = 0;
// Настройки
tableSize = Rms.lastTableSize;
scoreTableSize = Rms.lastTableSize;
Camera.w = w;
Camera.h = h;
Camera.limit = 3000;
matrix = new Matrix3D();
text = new Text3D();
text.setText("Flood-It");
new Thread(this).start();
threadRun = true;
}
private void initMenuStrings() {
menuItems[MENU_MAIN] = new String[] {
Language.getMessage(Language.START),
Language.getMessage(Language.HIGH_SCORE),
Language.getMessage(Language.OPTIONS),
Language.getMessage(Language.HELP),
Language.getMessage(Language.EXIT)
};
menuItems[MENU_OPTIONS] = new String[] {
Language.getMessage(Language.TABLE_SIZE),
Language.getMessage(Language.LANGUAGE),
Language.getMessage(Language.RESET_SCORES),
Language.getMessage(Language.BACK)
};
}
public static void showMenu() {
threadRun = true;
Main.midlet.dsp.setCurrent(Main.midlet.menu);
}
public void paint(Graphics g) {
draw(G);
g.drawImage(I, 0, 0, Graphics.TOP | Graphics.LEFT);
}
/* Отрисовка в буфер */
private void draw(Graphics g) {
g.setColor(0x00);
g.fillRect(0, 0, w, h);
if (activeMenu != ITEM_SET_SIZE) text.paint(g, matrix);
g.setFont(font);
if (activeMenu == ITEM_HIGHSCORES) {
// Лучшие результаты
Main.midlet.hiscore.paintResults(g, scoreTableSize);
} else if (activeMenu == ITEM_SET_SIZE) {
// Установка размера поля
Main.midlet.floodit.paintTableOptions(g, tableSize);
} else {
// Отрисовываем фон курсора
int menuY = h - menuItems[activeMenu].length * fontHeight;
int menuW = w / 2;
int menuX = w / 2 - menuW / 2;
g.setGrayScale(100);
g.fillRect(menuX, menuY + menuCursor[activeMenu] * fontHeight, menuW, fontHeight);
g.setGrayScale(255);
for (int i = 0; i < menuItems[activeMenu].length; i++) {
g.drawString(menuItems[activeMenu][i], w / 2, menuY + i * fontHeight, Graphics.HCENTER | Graphics.TOP);
}
}
}
/**
* Преобразования
*/
private void conversions() {
// Сбросываем настройки матрицы
matrix.unit();
// Поворачиваем по всем осям
matrix.yrot(rotY);
// matrix.yrot(0);
matrix.zrot(rotZ);
rotY += 0.1;
rotZ += 0.2;
if (rotY > 360) rotY = 1;
if (rotZ > 360) rotZ = 1;
// Устанавливаем координаты модели
// matrix.translate(modelX, modelY, modelZ);
matrix.translate(0, h, 1600);
}
private void menuAction() {
if (activeMenu == MENU_MAIN) {
switch (menuCursor[activeMenu]) {
case 0: // Start Game
threadRun = false;
Main.midlet.floodit.game.setTableSize(tableSize);
Main.midlet.dsp.setCurrent(Main.midlet.floodit);
break;
case 1: // Hi-scores
activeMenu = ITEM_HIGHSCORES;
break;
case 2: // Options
activeMenu = MENU_OPTIONS;
break;
case 3: // Help
threadRun = false;
Main.midlet.about.setBackground(I);
Main.midlet.dsp.setCurrent(Main.midlet.about);
break;
case 4: // Exit
Main.midlet.destroyApp(true);
break;
}
} else if (activeMenu == MENU_OPTIONS) {
switch (menuCursor[activeMenu]) {
case 0:
activeMenu = ITEM_SET_SIZE;
break;
case 1:
Language.nextLanguage();
initMenuStrings();
Main.midlet.about = new About("about."+Language.getCurrentLanguage());
break;
case 2:
Main.midlet.hiscore.resetHiscores();
activeMenu = MENU_MAIN;
break;
case 3:// Back
activeMenu = MENU_MAIN;
break;
}
}
}
protected void sizeChanged(int w, int h) {
this.w = getWidth();
this.h = getHeight();
I = Image.createImage(w, h);
G = I.getGraphics();
super.sizeChanged(w, h);
}
protected void keyPressed(int key) {
int ga = getGameAction(key);
if (activeMenu == ITEM_SET_SIZE) {
keyTableOptions(ga, key);
} else if (activeMenu == ITEM_HIGHSCORES) {
keyHiscore(ga, key);
} else keyMenu(ga, key);
}
protected void keyRepeated(int key) {
keyPressed(key);
}
public void run() {
while (true) {
if (threadRun) {
conversions();
repaint();
}
try {
Thread.sleep(5L);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
}
private void keyMenu(int ga, int key) {
switch (ga) {
case FIRE:
menuAction();
break;
case LEFT:
case UP:
menuCursor[activeMenu]--;
if (menuCursor[activeMenu] < 0) {
menuCursor[activeMenu] = menuItems[activeMenu].length - 1;
}
break;
case RIGHT:
case DOWN:
menuCursor[activeMenu]++;
if (menuCursor[activeMenu] >= menuItems[activeMenu].length) {
menuCursor[activeMenu] = 0;
}
break;
default:
if ((key == -7) || (key == -6) || (key == KEY_STAR)) {
// Если в подменю - возврашаемся
if (activeMenu != MENU_MAIN) {
activeMenu = MENU_MAIN;
// Иначе выходим
} else {
Main.midlet.destroyApp(true);
}
}
}
}
private void keyTableOptions(int ga, int key) {
// Настройки размера окна
if ((ga == FIRE) || (key == -7) || (key == -6) || (key == KEY_STAR)) {
activeMenu = MENU_OPTIONS;
} else tableSize = changeTableSize(ga, key, tableSize);
}
private void keyHiscore(int ga, int key) {
// Настройки размера окна
if ((ga == FIRE) || (key == -7) || (key == -6) || (key == KEY_STAR)) {
activeMenu = MENU_MAIN;
} else scoreTableSize = changeTableSize(ga, key, scoreTableSize);
}
private int changeTableSize(int ga, int key, int size) {
// смена размера окна
switch (ga) {
case LEFT:
case DOWN:
if (size > Main.MIN_TABLE_SIZE) {
size--;
}
break;
case RIGHT:
case UP:
if (size < Main.MAX_TABLE_SIZE) {
size++;
}
break;
}
return size;
}
}

86
src/Rms.java Normal file
View File

@ -0,0 +1,86 @@
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import javax.microedition.rms.InvalidRecordIDException;
import javax.microedition.rms.RecordStore;
import javax.microedition.rms.RecordStoreException;
/**
*
* @author aNNiMON
*/
public class Rms {
private static final String rmsName = "Flood-It";
private static RecordStore rmsStore;
public static boolean firstStart = true; // первый старт
public static String language = "";
public static int lastTableSize = 14;
public static String playerName = "Player";
/**
* Сохранение настроек
*/
public static void saveOptions() {
if (rmsStore != null) {
byte[] options = null;
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(baos);
dos.writeBoolean(false);//firstStart
dos.writeUTF(language);
dos.writeInt(lastTableSize);
dos.writeUTF(playerName);
Main.midlet.hiscore.saveScores(dos);
dos.flush();
options = encode(baos.toByteArray());
dos.close();
rmsStore.setRecord(1, options, 0, options.length);
} catch (InvalidRecordIDException ridex) {
try {
rmsStore.addRecord(options, 0, options.length);
} catch (RecordStoreException ex) {}
} catch (Exception ex) {
}
}
if (rmsStore != null) {
try {
rmsStore.closeRecordStore();
rmsStore = null;
} catch (RecordStoreException ex) {}
}
}
/**
* Восстановить настройки
*/
public static void restoreOptions() {
try {
rmsStore = RecordStore.openRecordStore(rmsName, true);
} catch (RecordStoreException ex) {
rmsStore = null;
}
if (rmsStore != null) {
try {
byte[] data = encode(rmsStore.getRecord(1));
DataInputStream dis = new DataInputStream(new ByteArrayInputStream(data));
firstStart = dis.readBoolean();
language = dis.readUTF();
lastTableSize = dis.readInt();
playerName = dis.readUTF();
Main.midlet.hiscore.loadScores(dis);
dis.close();
} catch (Exception ex) {}
}
}
private static byte[] encode(byte[] data) {
for (int i = 0; i < data.length; i++) {
data[i] ^= 119;
}
return data;
}
}

73
src/SoftBar.java Normal file
View File

@ -0,0 +1,73 @@
import com.s3d.Camera;
import com.s3d.Matrix3D;
import com.s3d.Mesh;
import javax.microedition.lcdui.Graphics;
/*
* aNNiMON 2012
* For more info visit http://annimon.com/
*/
/**
* Софтбар с выбором цвета для заливки
* @author aNNiMON
*/
public class SoftBar {
private Matrix3D[] matrix;
private Mesh[] mesh;
private double[][] rotate;
public SoftBar() {
mesh = new Mesh[Main.MAX_COLORS];
matrix = new Matrix3D[Main.MAX_COLORS];
rotate = new double[Main.MAX_COLORS][];
for (int i = 0; i < mesh.length; i++) {
mesh[i] = new Box(Main.BOX_SIZE).getBox(Main.COLORS[i]);
// int x = ((i - mesh.length) / 2) * Main.BOX_SIZE;
// mesh[i].move(x, 0, 0);
//
matrix[i] = new Matrix3D();
rotate[i] = new double[] { 0, 0, 0 };
}
}
public void paint(Graphics g, byte active) {
int h = g.getClipHeight();
int tempW = Camera.w;
int tempH = Camera.h;
Camera.w = g.getClipWidth() / mesh.length;
Camera.h = h / mesh.length;
for (int i = 0; i < mesh.length; i++) {
matrix[i].unit();
// Поворачиваем по всем осям
matrix[i].xrot(rotate[i][1]);
matrix[i].yrot(rotate[i][0]);
matrix[i].zrot(rotate[i][2]);
// Устанавливаем координаты модели
matrix[i].translate(0, 0, 550);
if ((i == active) || (active == -1)) {
for (int j = 0; j <= 2; j++) {
rotate[i][j] += 5;
if (rotate[i][j] > 360) {
rotate[i][j] = 1;
}
}
}
g.translate(Camera.w * i, h - Camera.h - i);
mesh[i].paint(g, matrix[i]);
g.translate(-Camera.w * i, -(h - Camera.h - i));
}
Camera.w = tempW;
Camera.h = tempH;
}
}

24
src/StringEncoder.java Normal file
View File

@ -0,0 +1,24 @@
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;
}
}

53
src/Table.java Normal file
View File

@ -0,0 +1,53 @@
import com.s3d.Matrix3D;
import com.s3d.Mesh;
import javax.microedition.lcdui.Graphics;
/*
* aNNiMON 2012
* For more info visit http://annimon.com/
*/
/**
*
* @author aNNiMON
*/
public class Table {
private Mesh[][] mesh;
public Table(int tableSize) {
mesh = new Mesh[tableSize][tableSize];
for (int i = 0; i < tableSize; i++) {
for (int j = 0; j < tableSize; j++) {
mesh[i][j] = new Box(Main.BOX_SIZE).getBox(0x00);
int x = (i - tableSize / 2) * Main.BOX_SIZE;
int y = (j - tableSize / 2) * Main.BOX_SIZE;
mesh[i][j].move(x, -y, 0);
}
}
}
public void updateTable(byte[][] table) {
int tableSize = table.length;
for (int i = 0; i < tableSize; i++) {
for (int j = 0; j < tableSize; j++) {
byte id = table[i][j];
mesh[i][j] = Util.setModelColor(mesh[i][j], Main.COLORS[id]);
}
}
}
public void paint(Graphics g, Matrix3D matrix) {
int tableSize = mesh.length;
for (int i = 0; i < tableSize; i++) {
for (int j = 0; j < tableSize; j++) {
mesh[i][j].paint(g, matrix);
}
}
}
}

138
src/Text3D.java Normal file
View File

@ -0,0 +1,138 @@
import com.s3d.Matrix3D;
import com.s3d.Mesh;
import javax.microedition.lcdui.Font;
import javax.microedition.lcdui.Graphics;
import javax.microedition.lcdui.Image;
/*
* aNNiMON 2012
* For more info visit http://annimon.com/
*/
/**
* Создание и отрисовка 3D текста
* @author aNNiMON
*/
public class Text3D {
private Mesh[][] mesh;
/**
* Установить текст для отображения в виде 3D
* @param text текст
*/
public void setText(String text) {
Image img = getImageFromText(text, 0x00, 0xFFFFFF);
int w = img.getWidth();
int h = img.getHeight();
int[] pix = new int[w * h];
img.getRGB(pix, 0, w, 0, 0, w, h);
img = null;
createMeshes(pix, w, h);
}
/**
* Отрисовка 3D текста
* @param g контекст графики
* @param matrix матрица преобразований
*/
public void paint(Graphics g, Matrix3D matrix) {
for (int i = 0; i < mesh.length; i++) {
for (int j = 0; j < mesh[i].length; j++) {
if (mesh[i][j] == null) {
continue;
}
mesh[i][j].paint(g, matrix);
}
}
}
/**
* Создать набор моделей в виде текста
* @param pix массив цветов
* @param w ширина массива
* @param h высота
*/
private void createMeshes(int[] pix, int w, int h) {
mesh = new Mesh[h][w];
boolean[] medianColor = getMedian(pix);
for (int i = 0; i < h; i++) {
// mesh[i] = new Mesh[h];
for (int j = 0; j < w; j++) {
// Пропускаем фоновые пиксели
if (!medianColor[i * w + j]) {
continue;
}
int meshColor = Main.COLORS[Util.random(0, Main.MAX_COLORS)];
mesh[i][j] = new Box(Main.BOX_SIZE).getBox(meshColor);
int x = (j - w / 2) * Main.BOX_SIZE;
int y = (i - h / 2) * Main.BOX_SIZE;
mesh[i][j].move(x, -y, 0);
}
}
}
/**
* Получить картинку с текстом
* @param text текст
* @param bgcolor цвет фона
* @param textcolor цвет текста
* @return картинка с текстом
*/
private Image getImageFromText(String text, int bgcolor, int textcolor) {
Font smallFont = Font.getFont(Font.FACE_SYSTEM, Font.STYLE_PLAIN, Font.SIZE_SMALL);
int width = smallFont.stringWidth(text);
int height = smallFont.getHeight();
Image out = Image.createImage(width, height);
Graphics g = out.getGraphics();
g.setColor(bgcolor);
g.fillRect(0, 0, width, height);
g.setFont(smallFont);
g.setColor(textcolor);
g.drawString(text, 0, 0, 20);
return out;
}
/**
* Получить черно-белую матрицу по усреднённому цвету
* @param pix массив цветов
* @return усреднённый цвет
*/
private boolean[] getMedian(int[] pix) {
float size = pix.length;
float mr = 0;
for (int i = 0; i < pix.length; i++) {
float r = ((pix[i] >> 16) & 0xFF);
r = r + ((pix[i] >> 8) & 0xFF);
r = r + (pix[i] & 0xFF);
r /= 3;
mr = mr + (r / size);
}
boolean[] out = new boolean[pix.length];
for (int i = 0; i < pix.length; i++) {
float r = ((pix[i] >> 16) & 0xFF);
r = r + ((pix[i] >> 8) & 0xFF);
r = r + (pix[i] & 0xFF);
r /= 3;
out[i] = (r > mr);
}
return out;
}
}

182
src/Util.java Normal file
View File

@ -0,0 +1,182 @@
import com.s3d.Mesh;
import com.s3d.Face;
import java.io.DataInputStream;
import java.util.Random;
import java.util.Vector;
import javax.microedition.lcdui.Image;
/*
* aNNiMON 2011
* For more info visit http://annimon.com/
*/
/**
*
* @author aNNiMON
*/
public class Util {
private static final Random rnd = new Random();
/* Получить случайное значение в промежутке (from..to) */
public static int random(int from, int to) {
return rnd.nextInt(to - from) + from;
}
/**
* Установить цвет модели mesh
* @param mesh модель, в которой нужно изменить цвет
* @param color цвет в формате RGB
* @return модель с изменённым цветом
*/
public static Mesh setModelColor(Mesh mesh, int color) {
int size = mesh.faces.size();
for (int i = 0; i < size; i++) {
Face face = (Face) mesh.faces.elementAt(i);
face.color = color;
mesh.faces.setElementAt(face, i);
}
return mesh;
}
/**
* Получить список доступных языков
* @param path путь к файлу ресурсов
* @return массив строк
*/
public static String[] getLanguages(String path) {
String[] lines = splitString(getText(path, false), " ");
for (int i = 0; i < lines.length; i++) {
lines[i] = lines[i].trim().toLowerCase();
}
return lines;
}
/**
* Открыть текст из файла ресурсов
* @param path путь к файл
* @param protect true - файл с защитой
* @return текст
*/
public static String getText(String path, boolean protect) {
DataInputStream dis = new DataInputStream(Runtime.getRuntime().getClass().getResourceAsStream("/"+path));
StringBuffer strBuff = new StringBuffer();
try {
int ch;
while ((ch = dis.read()) != -1) {
byte bt = (byte) ch;
if (protect) bt = (byte) (ch ^ 119);
strBuff.append(StringEncoder.decodeCharCP1251(bt));
}
dis.close();
} catch (Exception e) {
e.printStackTrace();
}
return strBuff.toString();
}
/**
* Разделение строки на массив подстрок
* @param str исходная строка
* @param delim строка-разделитель
* @return массив подстрок, разбитых по разделителю
*/
public static String[] splitString(String str, String delim) {
if ((str.length() == 0) || (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;
}
public static Image smooth(Image img, int blurHor, int blurVer) {
int w = img.getWidth();
int h = img.getHeight();
int[] pix = new int[w * h];
img.getRGB(pix, 0, w, 0, 0, w, h);
int[] pixel = new int[pix.length];
pixel = BoxBlur(pix, pixel, w, h, blurHor);
pix = BoxBlur(pixel, pix, h, w, blurVer);
return Image.createRGBImage(pix, w, h, false);
}
private static int[] BoxBlur(int[] in, int[] out, int width, int height, int radius) {
if (radius <= 0) {
return in;
}
int widthMinus1 = width - 1;
int tableSize = 2 * radius + 1;
int divideLength = 256 * tableSize;
int[] divide = new int[divideLength];
for (int i = 0; i < divideLength; i++) {
divide[i] = i / tableSize;
}
int inIndex = 0;
for (int y = 0; y < height; y++) {
int outIndex = y;
int tr = 0, tg = 0, tb = 0;
for (int i = -radius; i <= radius; i++) {
int rgb = in[inIndex + clamp(i, 0, widthMinus1)];
tr += (rgb >> 16) & 0xff;
tg += (rgb >> 8) & 0xff;
tb += rgb & 0xff;
}
for (int x = 0; x < width; x++) {
out[outIndex] = (255 << 24) | (divide[tr] << 16) | (divide[tg] << 8) | divide[tb];
int i1 = x + radius + 1;
if (i1 > widthMinus1) i1 = widthMinus1;
int i2 = x - radius;
if (i2 < 0) i2 = 0;
int rgb1 = in[inIndex + i1];
int rgb2 = in[inIndex + i2];
tr += ((rgb1 & 0xff0000) - (rgb2 & 0xff0000)) >> 16;
tg += ((rgb1 & 0xff00) - (rgb2 & 0xff00)) >> 8;
tb += (rgb1 & 0xff) - (rgb2 & 0xff);
outIndex += height;
}
inIndex += width;
}
return out;
}
private static int clamp(int x, int a, int b) {
return (x < a) ? a : (x > b) ? b : x;
}
}

BIN
src/about.en Normal file

Binary file not shown.

BIN
src/about.ru Normal file

Binary file not shown.

9
src/com/s3d/Camera.java Normal file
View File

@ -0,0 +1,9 @@
package com.s3d;
public class Camera {
public static int w = 132;
public static int h = 176;
public static int limit = 2000;
}

19
src/com/s3d/Face.java Normal file
View File

@ -0,0 +1,19 @@
package com.s3d;
import javax.microedition.lcdui.Graphics;
public abstract class Face {
public int color;
public abstract int getS();
public abstract void paint(Graphics g, boolean flag);
public abstract void paint(Graphics g, int i);
public abstract void move(int i, int j, int k);
public abstract void setMatrix(Matrix3D matrix3d);
}

81
src/com/s3d/Matrix3D.java Normal file
View File

@ -0,0 +1,81 @@
package com.s3d;
public class Matrix3D {
float xx, xy, xz, xo;
float yx, yy, yz, yo;
float zx, zy, zz, zo;
public Matrix3D() {
xx = 1.0F;
yy = 1.0F;
zz = 1.0F;
}
public void translate(float x, float y, float z) {
xo += x;
yo += y;
zo += z;
}
public void yrot(double d) {
d *= 0.017453292519943295D;
double d1 = Math.cos(d);
double d2 = Math.sin(d);
float f0 = (float) (xx * d1 + zx * d2);
float f1 = (float) (xy * d1 + zy * d2);
float f2 = (float) (xz * d1 + zz * d2);
float f3 = (float) (xo * d1 + zo * d2);
zx = (float) (zx * d1 - xx * d2);
zy = (float) (zy * d1 - xy * d2);
zz = (float) (zz * d1 - xz * d2);
zo = (float) (zo * d1 - xo * d2);
xo = f3;
xx = f0;
xy = f1;
xz = f2;
}
public void xrot(double d) {
d *= 0.017453292519943295D;
double d1 = Math.cos(d);
double d2 = Math.sin(d);
float f0 = (float) (yx * d1 + zx * d2);
float f1 = (float) (yy * d1 + zy * d2);
float f2 = (float) (yz * d1 + zz * d2);
float f3 = (float) (yo * d1 + zo * d2);
zx = (float) (zx * d1 - yx * d2);
zy = (float) (zy * d1 - yy * d2);
zz = (float) (zz * d1 - yz * d2);
zo = (float) (zo * d1 - yo * d2);
yo = f3;
yx = f0;
yy = f1;
yz = f2;
}
public void zrot(double d) {
d *= 0.017453292519943295D;
double d1 = Math.cos(d);
double d2 = Math.sin(d);
float f0 = (float) (yx * d1 + xx * d2);
float f1 = (float) (yy * d1 + xy * d2);
float f2 = (float) (yz * d1 + xz * d2);
float f3 = (float) (yo * d1 + xo * d2);
xx = (float) (xx * d1 - yx * d2);
xy = (float) (xy * d1 - yy * d2);
xz = (float) (xz * d1 - yz * d2);
xo = (float) (xo * d1 - yo * d2);
yo = f3;
yx = f0;
yy = f1;
yz = f2;
}
public void unit() {
xo = 0; xx = 1; xy = 0; xz = 0;
yo = 0; yx = 0; yy = 1; yz = 0;
zo = 0; zx = 0; zy = 0; zz = 1;
}
}

64
src/com/s3d/Mesh.java Normal file
View File

@ -0,0 +1,64 @@
package com.s3d;
import java.util.Vector;
import javax.microedition.lcdui.Graphics;
public class Mesh {
public Vector faces;
private static final int[] d = {
1, 4, 10, 23, 57, 145, 356, 911, 1968, 4711, 11969, 27901,
84801, 213331, 543749, 1355339, 3501671, 8810089, 21521774,
58548857, 157840433, 410151271, 0x436f7079, 2147483647
};
public Mesh() {
faces = new Vector();
}
public void paint(Graphics g, Matrix3D matrix3d) {
if (faces.isEmpty() || g == null || matrix3d == null) {
return;
}
sort(faces);
for (int i = faces.size() - 1; i >= 0; i--) {
//try {
Face face = (Face) faces.elementAt(i);
face.setMatrix(matrix3d);
face.paint(g, true);
//} catch (Exception exception) {}
}
}
public void addFace(Face face) {
faces.addElement(face);
}
public void move(int i, int j, int k) {
for (int l = 0; l < faces.size(); l++) {
((Face) faces.elementAt(l)).move(i, j, k);
}
}
private void sort(Vector vector) {
int l = 0;
int i1 = vector.size();
while (d[l] < i1) l++;
//for (i1 = vector.size(); d[l] < i1; l++) {}
while (--l >= 0) {
int k = d[l];
for (int i = k; i < i1; i++) {
int j = i;
Face face = (Face) vector.elementAt(i);
for (int j1 = face.getS(); j >= k && ((Face) vector.elementAt(j - k)).getS() > j1; j -= k) {
vector.setElementAt(vector.elementAt(j - k), j);
}
vector.setElementAt(face, j);
}
}
}
}

106
src/com/s3d/Square.java Normal file
View File

@ -0,0 +1,106 @@
package com.s3d;
import javax.microedition.lcdui.Graphics;
public class Square extends Face {
private Vertex v1, v2, v3, v4;
private float nx, ny, nz;
private float rnz;
private float k;
public Square(Vertex vertex, Vertex vertex1, Vertex vertex2, Vertex vertex3, int color) {
v1 = vertex3;
v2 = vertex1;
v3 = vertex;
super.color = color;
float f = (v1.y - v2.y) * (v2.z - v3.z) - (v1.z - v2.z) * (v2.y - v3.y);
float f1 = (v1.z - v2.z) * (v2.x - v3.x) - (v1.x - v2.x) * (v2.z - v3.z);
float f2 = (v1.x - v2.x) * (v2.y - v3.y) - (v1.y - v2.y) * (v2.x - v3.x);
double d = Math.sqrt(f * f + f1 * f1 + f2 * f2);
f = (float) (f / d);
f1 = (float) (f1 / d);
f2 = (float) (f2 / d);
v1 = vertex3;
v2 = vertex2;
v3 = vertex1;
float f3 = (v1.y - v2.y) * (v2.z - v3.z) - (v1.z - v2.z) * (v2.y - v3.y);
float f4 = (v1.z - v2.z) * (v2.x - v3.x) - (v1.x - v2.x) * (v2.z - v3.z);
float f5 = (v1.x - v2.x) * (v2.y - v3.y) - (v1.y - v2.y) * (v2.x - v3.x);
d = Math.sqrt(f3 * f3 + f4 * f4 + f5 * f5);
f3 = (float) (f3 / d);
f4 = (float) (f4 / d);
f5 = (float) (f5 / d);
nx = (f + f3) / 2f;
ny = (f1 + f4) / 2f;
rnz = nz = (f2 + f5) / 2f;
v1 = vertex;
v2 = vertex1;
v3 = vertex2;
v4 = vertex3;
}
public int getS() {
return (v1.zc + v2.zc + v3.zc + v4.zc) / 4;
}
public void paint(Graphics graphics, boolean flag) {
if (flag) {
k = rnz;
if (k > 0f) k = -k;
if (k < -1f) k = -1f;
int r = (super.color >> 16) & 0xff;
int g = (super.color >> 8) & 0xff;
int b = super.color & 0xff;
r = (int) (r * -k);
g = (int) (g * -k);
b = (int) (b * -k);
paint(graphics, (r << 16) | (g << 8) | b);
} else {
paint(graphics, super.color);
}
}
public void paint(Graphics g, int i) {
if (topaint()) {
g.setColor(i);
g.fillTriangle(v1.sx, v1.sy, v2.sx, v2.sy, v3.sx, v3.sy);
g.fillTriangle(v1.sx, v1.sy, v3.sx, v3.sy, v4.sx, v4.sy);
}
}
public void setMatrix(Matrix3D matrix3d) {
v1.setMatrix(matrix3d);
v2.setMatrix(matrix3d);
v3.setMatrix(matrix3d);
v4.setMatrix(matrix3d);
rnz = nx * matrix3d.zx + ny * matrix3d.zy + nz * matrix3d.zz;
}
public void move(int i, int j, int l) {
v1.move(i, j, l);
v2.move(i, j, l);
v3.move(i, j, l);
v4.move(i, j, l);
}
private boolean topaint() {
if (v1.zc < 0 || v2.zc < 0 || v3.zc < 0 || v4.zc < 0) {
return false;
}
if (v1.zc > Camera.limit && v2.zc > Camera.limit && v3.zc > Camera.limit && v4.zc > Camera.limit) {
return false;
}
if (v1.sx <= 0 && v2.sx <= 0 && v3.sx <= 0 && v4.sx <= 0) {
return false;
}
if (v1.sx >= Camera.w && v2.sx >= Camera.w && v3.sx >= Camera.w && v4.sx >= Camera.w) {
return false;
}
if (v1.sy <= 0 && v2.sy <= 0 && v3.sy <= 0 && v4.sy <= 0) {
return false;
}
return v1.sy < Camera.h || v2.sy < Camera.h || v3.sy < Camera.h || v4.sy < Camera.h;
}
}

42
src/com/s3d/Vertex.java Normal file
View File

@ -0,0 +1,42 @@
package com.s3d;
public class Vertex {
private static final int perx = 300;
private static final int pery = 300;
public int sx, sy;
public int zc;
public int x, y, z;
private int xc, yc;
public Vertex(int i, int j, int k) {
x = i;
y = j;
z = k;
}
public void setMatrix(Matrix3D matrix3d) {
xc = (int) (x * matrix3d.xx + y * matrix3d.xy + z * matrix3d.xz);
yc = (int) (x * matrix3d.yx + y * matrix3d.yy + z * matrix3d.yz);
zc = (int) (x * matrix3d.zx + y * matrix3d.zy + z * matrix3d.zz);
xc += matrix3d.xo;
yc += matrix3d.yo;
zc += matrix3d.zo;
to2d();
}
public void move(int i, int j, int k) {
x += i;
y += j;
z += k;
}
private void to2d() {
int k = (zc <= 0) ? -1 : zc;
int i = (xc * perx) / k;
int j = (yc * pery) / k;
sx = Camera.w / 2 + i;
sy = Camera.h / 2 - j;
}
}

17
src/en.lang Normal file
View File

@ -0,0 +1,17 @@
Start
Options
High score
Help
Exit
Table size
Language
Reset scores
Back
Position
Rotate
Game Over
Moves:
New high score:
Enter your name
Ok
Unknown

BIN
src/icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 874 B

1
src/langs.txt Normal file
View File

@ -0,0 +1 @@
en ru

17
src/ru.lang Normal file
View File

@ -0,0 +1,17 @@
Старт
Настройки
Рекорды
Помощь
Выход
Размер поля
Язык
Сброс
Назад
Позиция
Поворот
Игра окончена
Ходов:
Новый рекорд:
Введите имя
Ok
Аноним