/*
* Copyright 2010 Ian Bollinger
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package edu.worcester.subter;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import javax.media.j3d.AmbientLight;
import javax.media.j3d.Appearance;
import javax.media.j3d.BoundingSphere;
import javax.media.j3d.BranchGroup;
import javax.media.j3d.DirectionalLight;
import javax.media.j3d.LinearFog;
import javax.media.j3d.PointLight;
import javax.media.j3d.Transform3D;
import javax.media.j3d.TransformGroup;
import javax.vecmath.Color3f;
import javax.vecmath.Point3d;
import javax.vecmath.Vector3d;
import javax.vecmath.Vector3f;
import com.sun.j3d.utils.geometry.Box;
import com.sun.j3d.utils.geometry.Primitive;
import com.sun.j3d.utils.geometry.Sphere;
import edu.worcester.subter.j3d.Appearances;
import edu.worcester.subter.j3d.Transforms;
public final class MazeBuilder {
private static final int LENGTH = 40;
private static final double USER_HEIGHT = 1.0;
private static final float RADIUS = 0.5f;
private static final float HEIGHT = 3f;
private static final String BLOCK_TEXTURE = "src/main/resources/wall.png";
private static final String BANNER_TEXTURE = "src/main/resources/wall_banner.png";
private static final char STARTING_POSITION = 's';
private static final char BLOCK = 'b';
private static final char BANNER = 'B';
private static final char LIGHT = 'L';
private static TransformGroup makeObstacle(int x, int z,
Appearance appearance) {
final Primitive obstruction = new Box(RADIUS, HEIGHT / 2, RADIUS,
Primitive.GENERATE_TEXTURE_COORDS | Primitive.GENERATE_NORMALS,
appearance);
final Vector3d position = new Vector3d(x, HEIGHT / 2, z);
final Transform3D transform = Transforms.translation(position);
final TransformGroup transformGroup = new TransformGroup(transform);
transformGroup.addChild(obstruction);
return transformGroup;
}
private static TransformGroup makeLight(int x, int z) {
final Vector3d position = new Vector3d(x, HEIGHT / 2, z);
final Transform3D transform = Transforms.translation(position);
final TransformGroup transformGroup = new TransformGroup(transform);
final PointLight light = new PointLight();
light.setInfluencingBounds(new BoundingSphere(new Point3d(position), 20));
light.setAttenuation(0, 0, 1);
transformGroup.addChild(light);
return transformGroup;
}
private final Appearance blockAppearance = Appearances
.fromFile(BLOCK_TEXTURE);
private final Appearance bannerAppearance = Appearances
.fromFile(BANNER_TEXTURE);
private final BranchGroup branchGroup = new BranchGroup();
private final char[][] maze = new char[LENGTH][LENGTH];
private int startPositionX;
private int startPositionZ;
public MazeBuilder(String fileName) {
readFile(fileName);
buildLevel();
}
private void buildLevel() {
final BoundingSphere bounds = new BoundingSphere(new Point3d(),
Double.MAX_VALUE);
final LinearFog fog = new LinearFog(0f, 0f, 0f, 3f, 5f);
fog.setInfluencingBounds(bounds);
branchGroup.addChild(fog);
for (int z = 0; z < LENGTH; ++z) {
for (int x = 0; x < LENGTH; ++x) {
switch (maze[z][x]) {
case BLOCK:
branchGroup
.addChild(makeObstacle(x, z, blockAppearance));
break;
case BANNER:
branchGroup.addChild(makeObstacle(x, z,
bannerAppearance));
break;
case LIGHT:
branchGroup.addChild(makeLight(x, z));
break;
case STARTING_POSITION:
startPositionX = x;
startPositionZ = z;
branchGroup.addChild(makeLight(x, z));
}
}
}
}
public BranchGroup getMaze() {
return branchGroup;
}
public Vector3d getStartPosition() {
return new Vector3d(startPositionX, USER_HEIGHT, startPositionZ);
}
private void readFile(String fileName) {
try {
final BufferedReader reader = new BufferedReader(new FileReader(
fileName));
try {
for (int rows = 0; rows < LENGTH; ++rows) {
final String line = reader.readLine();
if (line == null) {
break;
}
for (int x = 0; x < LENGTH && x < line.length(); ++x) {
maze[rows][x] = line.charAt(x);
}
}
} finally {
reader.close();
}
} catch (final IOException e) {
throw new RuntimeException("Error reading level from " + fileName);
}
}
}