package com.opensoft.game;
import java.applet.Applet;
import java.awt.Frame;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferInt;
import java.util.Random;
private static final long serialVersionUID = 1L;
private static final String version
= "0.0.1";
// // screen dimensions: scale x4 - low fidelity
// private static final int WIDTH = 214;
// private static final int HEIGHT = 120;
// private static final int SCALE = 4;
// screen dimensions: scale x2 - high fidelity
// private static final int WIDTH = 428;
// private static final int HEIGHT = 240;
// private static final int SCALE = 2;
private static final int WIDTH = 640;
private static final int HEIGHT = 400;
private static final int SCALE = 1;
// the block world map is stored in a cube of sides 64 in length;
// each map entry determines the colour of the corresponding block
private static final int MAPDIM = 64; // map dimensions
private static final int MAPCUBE = MAPDIM * MAPDIM * MAPDIM; // value 262144
private int[] map = new int[MAPCUBE];
public static void main
(String[] args
) { Frame f
= new Frame("Minecraft4k Java Demo " + version
); @Override
public void windowClosing
(java.
awt.
event.
WindowEvent e
) { };
});
Minecraft4k mc = new Minecraft4k();
mc.setSize(WIDTH * SCALE, HEIGHT * SCALE);
f.add(mc);
f.pack();
mc.start();
f.setSize(WIDTH * SCALE, HEIGHT * SCALE);
f.setVisible(true);
}
@Override
public void start() {
new Thread(this).
start(); // triggers the run() method }
/*
* The following textures are generated
* 0 Air
* 1 Grass + Dirt
* 2 Dirt
* 3 Dirt
* 4 Stone (gray)
* 5 Brick
* 6 Dirt
* 7 Wood
* 8 Tree leaves
* 9 Water
* 10 .. 13 Dirt
* 14 Stone with moss
* 15 Red Brick with moss
*/
private int[] generate_textures() {
// Algorithmically generate textures...
int[] texmap = new int[12288]; // 16 * 16 * 16 * 3 = 12288
int i = 1;
while (i < 16) {
int lBrightness = 255 - rand.nextInt(96);
int y = 0;
while (y < (16 * 3)) { // 3 texture images (top, side and bottom),
// stored one below the other
int x = 0;
while (x < 16) {
int lBrightness2;
int lColor;
int color = 0x966C4A; // ground
if (i == 4) {
color = 0x7F7F7F; // stone
}
if (i != 4 || rand.nextInt(3) == 0) {
lBrightness = 255 - rand.nextInt(96);
}
if (i == 1 && y < (x * x * 3 + x * 81 >> 2 & 3) + 18) {
color = 0x6AAA40; // grass
} else if (i == 1 && y < (x * x * 3 + x * 81 >> 2 & 3) + 19) {
lBrightness = lBrightness * 2 / 3;
}
if (i == 7) {
color = 0x675231; // wood
if (x > 0 && x < 15 && (y > 0 && y < 15 || y > 32 && y < 47)) {
color = 0xBC9862; // wood
// This is WRONG - see the JavaScript version for
// details
lBrightness2 = x - 7;
lColor = (y & 15) - 7;
if (lBrightness2 < 0) {
lBrightness2 = 1 - lBrightness2;
}
if (lColor < 0) {
lColor = 1 - lColor;
}
if (lColor > lBrightness2) {
lBrightness2 = lColor;
}
lBrightness = 196 - rand.nextInt(32) + lBrightness2 % 3 * 32;
} else if (rand.nextInt(2) == 0) {
lBrightness = lBrightness * (150 - (x & 1) * 100) / 100;
}
}
if (i == 5) {
color = 0xB53A15; // brick
if ((x + y / 4 * 4) % 8 == 0 || y % 4 == 0) {
color = 0xBCAFA5;
}
}
if (i == 9) {
color = 0x4040ff; // water
}
if (i == 14) {
color = 0x7F7F7F; // stone with moss
if (rand.nextInt(3) == 0) {
color = 0x6AAA40;
} else if ((x + y / 4 * 4) % 8 == 0 || y % 4 == 0) {
color = 0x6AAA60;
}
}
if (i == 15) {
color = 0xB53A15; // red bricks with moss
if (rand.nextInt(3) == 0) {
color = 0x6AAA40;
} else if ((x + y / 4 * 4) % 8 == 0 || y % 4 == 0) {
color = 0x6AAA60;
}
}
lBrightness2 = lBrightness;
if (y >= 32) {
lBrightness2 /= 2;
}
if (i == 8) {
color = 0x50D937; // leaves
if (rand.nextInt(2) == 0) {
color = 0;
lBrightness2 = 255;
}
}
lColor = (color >> 16 & 0xFF) * lBrightness2 / 0xFF << 16 //
| (color >> 8 & 0xFF) * lBrightness2 / 0xFF << 8 //
| (color & 0xFF) * lBrightness2 / 0xFF;
texmap[x + y * 16 + i * 256 * 3] = lColor;
++x;
}
++y;
}
++i;
}
return texmap;
}
private void generateMap() {
for (int x = 0; x < MAPDIM; x++) {
for (int y = 0; y < MAPDIM; y++) {
for (int z = 0; z < MAPDIM; z++) {
int i = (z << 12) | (y << 6) | x;
float yd = (y - 32.5f) * 0.4f;
float zd = (z - 32.5f) * 0.4f;
map[i] = rand.nextInt(16);
float th = rand.nextInt(256) / 256.0f;
if ((th
> (Math.
sqrt(Math.
sqrt(yd
* yd
+ zd
* zd
)) - 0.8f
)) || (th
< 0.5f
)) { map[i] = 0;
}
}
}
}
}
@Override
public void run() {
try {
long lastTime
= System.
currentTimeMillis(); int frames = 0;
int[] imgBufferData
= ((DataBufferInt) localBufferedImage.
getRaster().
getDataBuffer()).
getData();
// rand.setSeed(18295169);
generateMap();
int[] texmap = generate_textures();
do {
float l
= System.
currentTimeMillis() % 10000 / 10000.0f
; // System.out.println("now = " + l);
float ox = 32.5f + l * 64;
float oy = 32.0f;
float oz = 32.5f;
float xRot
= (float) ((float) Math.
sin(l
* Math.
PI * 2f
) * 0.4f
+ Math.
PI / 2f
); float yRot
= (float) Math.
cos(l
* Math.
PI * 2f
) * 0.4f
;
float xSin
= (float) Math.
sin(xRot
); float xCos
= (float) Math.
cos(xRot
); float ySin
= (float) Math.
sin(yRot
); float yCos
= (float) Math.
cos(yRot
);
int x = 0;
// raycaster: for each column
while (x < WIDTH) {
float ___xd = (x - WIDTH / 2) / (float) HEIGHT;
int y = 0;
while (y < HEIGHT) {
float __yd = (y - HEIGHT / 2) / (float) HEIGHT;
float __zd = 1.0f;
float ___zd = __zd * yCos + __yd * ySin;
float _yd = __yd * yCos - __zd * ySin;
float _xd = ___xd * xCos + ___zd * xSin;
float _zd = ___zd * xCos - ___xd * xSin;
int col = 0; // black sky colour
int br = 255; // brightness
double closest = 32.0d; // how far can we see
int d = 0;
while (d < 3) {
float dimLength = _xd;
if (d == 1) {
dimLength = _yd;
} else if (d == 2) {
dimLength = _zd;
}
float ll = 1.0f / (dimLength < 0.0f ? -dimLength : dimLength);
float xd = _xd * ll;
float yd = _yd * ll;
float zd = _zd * ll;
float initial = ox - ((int) ox);
if (d == 1) {
initial = oy - ((int) oy);
} else if (d == 2) {
initial = oz - ((int) oz);
}
if (dimLength > 0.0f) {
initial = 1.0f - initial;
}
float dist = ll * initial;
float xp = ox + xd * initial;
float yp = oy + yd * initial;
float zp = oz + zd * initial;
if (dimLength < 0.0f) {
if (d == 0) {
xp--;
} else if (d == 1) {
yp--;
} else if (d == 2) {
zp--;
}
}
// while we are considering a ray that is still closer then the best so far
while (dist < closest) {
// quantize to the map grid
int mapOffset = (((int) zp & 63) << 12) | (((int) yp & 63) << 6) | ((int) xp & 63);
int tex = map[mapOffset];
// if this voxel has a texture applied
if (tex > 0) {
// find the uv coordinates of the intersection point
int u = (int) ((xp + zp) * 16.0f) & 15;
int v = ((int) (yp * 16.0f) & 15) + 16;
// fix uv's for alternate directions?
if (d == 1) {
u = (int) (xp * 16.0f) & 15;
v = (int) (zp * 16.0f) & 15;
if (yd < 0.0f) {
v += 32;
}
}
// find the colour at the intersection point
int cc = texmap[u + v * 16 + tex * 256 * 3];
// if the colour is not transparent
if (cc > 0) {
col = cc;
br = 255 - (int) (dist / 32.0f * 255.0f);
br = br * (255 - (d + 2) % 3 * 50) / 255;
// we now have the closest hit point (also terminates this ray)
closest = dist;
}
}
// advance the ray
xp += xd;
yp += yd;
zp += zd;
dist += ll;
}
++d;
}
int r = (col >> 16 & 0xFF) * br / 0xFF;
int g = (col >> 8 & 0xFF) * br / 0xFF;
int b = (col & 0xFF) * br / 0xFF;
imgBufferData[x + y * WIDTH] = r << 16 | g << 8 | b;
++y;
}
++x;
}
// the following code is only needed for a Java Applet -
// disables application when not visible
// if (!this.isActive()) {
// return;
// }
frames++;
// Graphics g = localBufferedImage.getGraphics();
// g.setColor(Color.WHITE);
// Font stringFont = g.getFont().deriveFont(7.0f);
// g.setFont(stringFont);
// g.drawString(version, 2, 6);
// g.drawString(prevFrames + " fps", 2, 13);
this.getGraphics().drawImage(localBufferedImage, 0, 0, WIDTH * SCALE, HEIGHT * SCALE, null);
// FPS counter printed every 1 second.
while (System.
currentTimeMillis() - lastTime
> 1000) { System.
out.
println(frames
+ " fps"); lastTime += 1000;
frames = 0;
}
} while (true);
e.printStackTrace();
return;
}
}
}
[code]