Initial
This commit is contained in:
commit
67a3be6fcb
83
build.xml
Normal file
83
build.xml
Normal 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
1247
nbproject/build-impl.xml
Normal file
File diff suppressed because it is too large
Load Diff
8
nbproject/genfiles.properties
Normal file
8
nbproject/genfiles.properties
Normal 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
|
7
nbproject/private/private.properties
Normal file
7
nbproject/private/private.properties
Normal 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
|
4
nbproject/private/private.xml
Normal file
4
nbproject/private/private.xml
Normal 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>
|
105
nbproject/project.properties
Normal file
105
nbproject/project.properties
Normal 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
10
nbproject/project.xml
Normal 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
207
src/About.java
Normal 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
87
src/Box.java
Normal 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
284
src/Canv.java
Normal 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
135
src/FloodIt.java
Normal 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
136
src/Hiscores.java
Normal 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
72
src/Language.java
Normal 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
55
src/Main.java
Normal 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
326
src/Menu.java
Normal 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
86
src/Rms.java
Normal 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
73
src/SoftBar.java
Normal 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
24
src/StringEncoder.java
Normal 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
53
src/Table.java
Normal 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
138
src/Text3D.java
Normal 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
182
src/Util.java
Normal 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
BIN
src/about.en
Normal file
Binary file not shown.
BIN
src/about.ru
Normal file
BIN
src/about.ru
Normal file
Binary file not shown.
9
src/com/s3d/Camera.java
Normal file
9
src/com/s3d/Camera.java
Normal 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
19
src/com/s3d/Face.java
Normal 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
81
src/com/s3d/Matrix3D.java
Normal 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
64
src/com/s3d/Mesh.java
Normal 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
106
src/com/s3d/Square.java
Normal 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
42
src/com/s3d/Vertex.java
Normal 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
17
src/en.lang
Normal 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
BIN
src/icon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 874 B |
1
src/langs.txt
Normal file
1
src/langs.txt
Normal file
@ -0,0 +1 @@
|
||||
en ru
|
17
src/ru.lang
Normal file
17
src/ru.lang
Normal file
@ -0,0 +1,17 @@
|
||||
Старт
|
||||
Настройки
|
||||
Рекорды
|
||||
Помощь
|
||||
Выход
|
||||
Размер поля
|
||||
Язык
|
||||
Сброс
|
||||
Назад
|
||||
Позиция
|
||||
Поворот
|
||||
Игра окончена
|
||||
Ходов:
|
||||
Новый рекорд:
|
||||
Введите имя
|
||||
Ok
|
||||
Аноним
|
Loading…
Reference in New Issue
Block a user