From 67a3be6fcb8da1b27eb3287138264d85836f0974 Mon Sep 17 00:00:00 2001 From: Victor Date: Thu, 15 Nov 2018 00:06:29 +0200 Subject: [PATCH] Initial --- build.xml | 83 ++ nbproject/build-impl.xml | 1247 ++++++++++++++++++++++++++ nbproject/genfiles.properties | 8 + nbproject/private/private.properties | 7 + nbproject/private/private.xml | 4 + nbproject/project.properties | 105 +++ nbproject/project.xml | 10 + src/About.java | 207 +++++ src/Box.java | 87 ++ src/Canv.java | 284 ++++++ src/FloodIt.java | 135 +++ src/Hiscores.java | 136 +++ src/Language.java | 72 ++ src/Main.java | 55 ++ src/Menu.java | 326 +++++++ src/Rms.java | 86 ++ src/SoftBar.java | 73 ++ src/StringEncoder.java | 24 + src/Table.java | 53 ++ src/Text3D.java | 138 +++ src/Util.java | 182 ++++ src/about.en | Bin 0 -> 704 bytes src/about.ru | Bin 0 -> 830 bytes src/com/s3d/Camera.java | 9 + src/com/s3d/Face.java | 19 + src/com/s3d/Matrix3D.java | 81 ++ src/com/s3d/Mesh.java | 64 ++ src/com/s3d/Square.java | 106 +++ src/com/s3d/Vertex.java | 42 + src/en.lang | 17 + src/icon.png | Bin 0 -> 874 bytes src/langs.txt | 1 + src/ru.lang | 17 + 33 files changed, 3678 insertions(+) create mode 100644 build.xml create mode 100644 nbproject/build-impl.xml create mode 100644 nbproject/genfiles.properties create mode 100644 nbproject/private/private.properties create mode 100644 nbproject/private/private.xml create mode 100644 nbproject/project.properties create mode 100644 nbproject/project.xml create mode 100644 src/About.java create mode 100644 src/Box.java create mode 100644 src/Canv.java create mode 100644 src/FloodIt.java create mode 100644 src/Hiscores.java create mode 100644 src/Language.java create mode 100644 src/Main.java create mode 100644 src/Menu.java create mode 100644 src/Rms.java create mode 100644 src/SoftBar.java create mode 100644 src/StringEncoder.java create mode 100644 src/Table.java create mode 100644 src/Text3D.java create mode 100644 src/Util.java create mode 100644 src/about.en create mode 100644 src/about.ru create mode 100644 src/com/s3d/Camera.java create mode 100644 src/com/s3d/Face.java create mode 100644 src/com/s3d/Matrix3D.java create mode 100644 src/com/s3d/Mesh.java create mode 100644 src/com/s3d/Square.java create mode 100644 src/com/s3d/Vertex.java create mode 100644 src/en.lang create mode 100644 src/icon.png create mode 100644 src/langs.txt create mode 100644 src/ru.lang diff --git a/build.xml b/build.xml new file mode 100644 index 0000000..27c3400 --- /dev/null +++ b/build.xml @@ -0,0 +1,83 @@ + + + + + + Builds, tests, and runs the project . + + + diff --git a/nbproject/build-impl.xml b/nbproject/build-impl.xml new file mode 100644 index 0000000..6c12ecb --- /dev/null +++ b/nbproject/build-impl.xml @@ -0,0 +1,1247 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Classpath to J2ME Ant extension library (libs.j2me_ant_ext.classpath property) is not set. For example: location of mobility/modules/org-netbeans-mobility-antext.jar file in the IDE installation directory. + Platform home (platform.home property) is not set. Value of this property should be ${platform.active.description} emulator home directory location. + Platform boot classpath (platform.bootclasspath property) is not set. Value of this property should be ${platform.active.description} emulator boot classpath containing all J2ME classes provided by emulator. + Must set src.dir + Must set build.dir + Must set dist.dir + Must set dist.jar + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must set preprocessed.dir + + + + + + + + + + + + + + + + + + Must set build.classes.dir + + + + + + + + + + + + + + + + + + + + + Must select some files in the IDE or set javac.includes + + + + + + + + + + + + + + + + + + + + + + + + + + Must set obfuscated.classes.dir + + + + Must set obfuscated.classes.dir + Must set obfuscator.srcjar + Must set obfuscator.destjar + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must set preverify.classes.dir + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + MicroEdition-Configuration: ${platform.configuration} + + MicroEdition-Configuration: ${platform.configuration} + + + + MicroEdition-Profile: ${platform.profile} + + MicroEdition-Profile: ${platform.profile} + + + + Must set dist.jad + + + + + + + + + + + + + + + + + + + + + + + + ${manifest.midlets}${evaluated.manifest.apipermissions}${evaluated.manifest.pushregistry}${manifest.others}${manifest.jad} + ${manifest.midlets}${evaluated.manifest.apipermissions}${evaluated.manifest.pushregistry}${manifest.others}${manifest.manifest} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Starting emulator with port number ${active.debug.port} + + + + + + + + + + + + + + + + + Starting emulator with port number ${active.debug.port} + + + + + + + + + + + + + + + + + Must set dist.javadoc.dir + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ${all.configurations} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Property deployment.${deployment.method}.scriptfile not set. The property should point to an Ant script providing ${deployment.method} deployment. + + + + + + + + Classpath to Ant Contrib library (libs.ant-contrib.classpath property) is not set. + + + + + + + + + Active project configuration: @{cfg} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Property build.root.dir is not set. By default its value should be \"build\". + Property dist.root.dir is not set. By default its value should be \"dist\". + + + + + diff --git a/nbproject/genfiles.properties b/nbproject/genfiles.properties new file mode 100644 index 0000000..44a999e --- /dev/null +++ b/nbproject/genfiles.properties @@ -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 diff --git a/nbproject/private/private.properties b/nbproject/private/private.properties new file mode 100644 index 0000000..6657a08 --- /dev/null +++ b/nbproject/private/private.properties @@ -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 diff --git a/nbproject/private/private.xml b/nbproject/private/private.xml new file mode 100644 index 0000000..c1f155a --- /dev/null +++ b/nbproject/private/private.xml @@ -0,0 +1,4 @@ + + + + diff --git a/nbproject/project.properties b/nbproject/project.properties new file mode 100644 index 0000000..6eee123 --- /dev/null +++ b/nbproject/project.properties @@ -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 diff --git a/nbproject/project.xml b/nbproject/project.xml new file mode 100644 index 0000000..dbb903e --- /dev/null +++ b/nbproject/project.xml @@ -0,0 +1,10 @@ + + + org.netbeans.modules.kjava.j2meproject + + + S3DGame + 1.6 + + + diff --git a/src/About.java b/src/About.java new file mode 100644 index 0000000..bebd8a3 --- /dev/null +++ b/src/About.java @@ -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; + } + } + } +} diff --git a/src/Box.java b/src/Box.java new file mode 100644 index 0000000..9a1bfc0 --- /dev/null +++ b/src/Box.java @@ -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) + }; + } +} \ No newline at end of file diff --git a/src/Canv.java b/src/Canv.java new file mode 100644 index 0000000..dd670b7 --- /dev/null +++ b/src/Canv.java @@ -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(); + } + } + } +} \ No newline at end of file diff --git a/src/FloodIt.java b/src/FloodIt.java new file mode 100644 index 0000000..d2d10a9 --- /dev/null +++ b/src/FloodIt.java @@ -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; + } +} \ No newline at end of file diff --git a/src/Hiscores.java b/src/Hiscores.java new file mode 100644 index 0000000..22e4bec --- /dev/null +++ b/src/Hiscores.java @@ -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; + } + +} diff --git a/src/Language.java b/src/Language.java new file mode 100644 index 0000000..efd6ee3 --- /dev/null +++ b/src/Language.java @@ -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"); + } +} diff --git a/src/Main.java b/src/Main.java new file mode 100644 index 0000000..91e163c --- /dev/null +++ b/src/Main.java @@ -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(); + } +} \ No newline at end of file diff --git a/src/Menu.java b/src/Menu.java new file mode 100644 index 0000000..532d0cd --- /dev/null +++ b/src/Menu.java @@ -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; + } +} \ No newline at end of file diff --git a/src/Rms.java b/src/Rms.java new file mode 100644 index 0000000..5abb3b1 --- /dev/null +++ b/src/Rms.java @@ -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; + } +} + diff --git a/src/SoftBar.java b/src/SoftBar.java new file mode 100644 index 0000000..a4390e9 --- /dev/null +++ b/src/SoftBar.java @@ -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; + } +} \ No newline at end of file diff --git a/src/StringEncoder.java b/src/StringEncoder.java new file mode 100644 index 0000000..2c82a17 --- /dev/null +++ b/src/StringEncoder.java @@ -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; + } +} \ No newline at end of file diff --git a/src/Table.java b/src/Table.java new file mode 100644 index 0000000..3bc8e76 --- /dev/null +++ b/src/Table.java @@ -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); + } + } + } +} \ No newline at end of file diff --git a/src/Text3D.java b/src/Text3D.java new file mode 100644 index 0000000..ce6b7d6 --- /dev/null +++ b/src/Text3D.java @@ -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; + } +} \ No newline at end of file diff --git a/src/Util.java b/src/Util.java new file mode 100644 index 0000000..aa39743 --- /dev/null +++ b/src/Util.java @@ -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; + } +} \ No newline at end of file diff --git a/src/about.en b/src/about.en new file mode 100644 index 0000000000000000000000000000000000000000..12415b5c939067fb1cd953e4d689aa6fb1e5fe32 GIT binary patch literal 704 zcmZuvO>dh(5OrB7rzB>KSF?+?MEN+TJ*0=&CxcnI6#EisuuC^N!@g!`5n$b=-2k_>U-!C8(O&=O^|Afr4Ky1o=Mj2xnkGCI(t0=CWES+`YRe_MhZ!+9cUP=UYmEi6wP zRB+9QemvB+sI9HadS49VQ(cyat*x4}sLNrzv-NggZg6J$(2K1U+H{)5X_jVRH$tmg zRwSACdqs-`l#=3%ms%?1#Q-n_HD9B!v>M8Kw*TE{Qo5p9l4b#%fD^)cZkXg@Re}N` zm$a2IWqo>T&t!rAa>x3voXA72w*{Q z%*}@hIDdctUtC40Xl1?FtBv+zuSfNasr&>czYSye{v+y;h*6QX_P z93r-znLpXETw=v_s&!#Asb9h+mZcO+0FFf!oxt}!HyAr< zb{x3wWZ-)v*9qJ-d+Y~;u{#)!#*Q~JS#0%s-TsRnyz4jbce)SYN&8OYM(bwtEwIzW dc;v-c;;=Apm=qD#Xi8ufN literal 0 HcmV?d00001 diff --git a/src/com/s3d/Camera.java b/src/com/s3d/Camera.java new file mode 100644 index 0000000..c40ce89 --- /dev/null +++ b/src/com/s3d/Camera.java @@ -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; +} diff --git a/src/com/s3d/Face.java b/src/com/s3d/Face.java new file mode 100644 index 0000000..b104686 --- /dev/null +++ b/src/com/s3d/Face.java @@ -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); + +} diff --git a/src/com/s3d/Matrix3D.java b/src/com/s3d/Matrix3D.java new file mode 100644 index 0000000..eb6d26b --- /dev/null +++ b/src/com/s3d/Matrix3D.java @@ -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; + } +} diff --git a/src/com/s3d/Mesh.java b/src/com/s3d/Mesh.java new file mode 100644 index 0000000..3638d55 --- /dev/null +++ b/src/com/s3d/Mesh.java @@ -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); + } + } + } + +} diff --git a/src/com/s3d/Square.java b/src/com/s3d/Square.java new file mode 100644 index 0000000..d5c954e --- /dev/null +++ b/src/com/s3d/Square.java @@ -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; + } + +} diff --git a/src/com/s3d/Vertex.java b/src/com/s3d/Vertex.java new file mode 100644 index 0000000..35bdcad --- /dev/null +++ b/src/com/s3d/Vertex.java @@ -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; + } +} diff --git a/src/en.lang b/src/en.lang new file mode 100644 index 0000000..f5c305f --- /dev/null +++ b/src/en.lang @@ -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 \ No newline at end of file diff --git a/src/icon.png b/src/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..3745252b2f8882e7b259618fcd743c8fa6121c1d GIT binary patch literal 874 zcmV-w1C{)VP)kpuucCrH+(?wTkVj0T z0SiGv1vMH;j9Zs3b#FATj7B&5J9h{-gusHGPV#MLa=!D=nVZWn|LW2?pT+1Li?LfO z3f|ztmY*`*%O_!lvVn|C;%mBb?!4~}k$oZ{$vQH;S+@v+mQYQ&Y_{H=F52JruDj;g zHzLH;+;$KdB>g&M*0iB4|0X;+m%(Wor#BP&`Hri&vO3VBtH7k|0G2#an93JnG<7#Z zd*bj&DyB?HM9`^@&u%0W5x%U-Y_18sJ{5-LQw$aqv4VhSMjnS-MBJ}u;n&FF7ArZhZE$79IOh$!W*$R4fdi};^oZb=Dv|c75d^42H zqfpfjd%{J?dQ7xHZ>t8GBkGkWg@m3ml_1<%mxx58G-tiAi%(Z+=)t*oC;TNAG)%B) z8l&3m`=>&@oXGT6IjoB@`xf(!J6He!TQV2y-1O5b;7U6=pb| z2KfT7rH9Jqq!PIIHPga^lwRRlrh<^rq+Weekns#0Wl)xxkWGaub8j)>mqqQx6_FIZ zu~Ov83y`(f1-;6P6D`b8l^rk> z2JA^C6M>!L+142O3zOXTR=20QE1~N+-x346Gf2oJb6kWIP>a=Hr%r zTST~x5TW5*kwmB@Xc{vWW+HPCynR-tocV9oUrUA76F?l!b^rhX07*qoM6N<$f(6`> A*Z=?k literal 0 HcmV?d00001 diff --git a/src/langs.txt b/src/langs.txt new file mode 100644 index 0000000..845d552 --- /dev/null +++ b/src/langs.txt @@ -0,0 +1 @@ +en ru \ No newline at end of file diff --git a/src/ru.lang b/src/ru.lang new file mode 100644 index 0000000..9ee406f --- /dev/null +++ b/src/ru.lang @@ -0,0 +1,17 @@ + + + + + + + + + + + + +: + : + +Ok + \ No newline at end of file