Killer Game Programming in JavaFX - (Chapter 15)

So I was looking at Killer Game Programming in Java and decided to rewrite the first 3D chapter in JavaFX it turned out pretty well code below I don't think I am going to explain anything today...LOL.




Checkers3D.java
package io.skidrunner.killer_javafx.ch15;

import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.PerspectiveCamera;
import javafx.scene.PointLight;
import javafx.scene.Scene;
import javafx.scene.input.MouseEvent;
import javafx.scene.paint.Color;
import javafx.scene.paint.PhongMaterial;
import javafx.scene.shape.Sphere;
import javafx.scene.transform.Rotate;
import javafx.scene.transform.Translate;
import javafx.stage.Stage;

/**
 * Created by U292337 on 6/6/2017.
 */
public class Checkers3D extends Application {

    private final Group root = new Group();

    private PerspectiveCamera camera;
    private Rotate cameraRotateX, cameraRotateY, cameraRotateZ;
    private Translate cameraTranslate;

    private double mouseOldX, mouseNewX;
    private double mouseOldY, mouseNewY;

    public static void main(String[] args) {
        Checkers3D.launch(args);
    }

    @Override
    public void start(Stage stage) {
        // Create Camera
        camera = new PerspectiveCamera(true);
        cameraRotateX = new Rotate(0, Rotate.X_AXIS);
        cameraRotateY = new Rotate(0, Rotate.Y_AXIS);
        cameraRotateZ = new Rotate(0, Rotate.Z_AXIS);
        cameraTranslate = new Translate(0, 0, -25);
        camera.getTransforms().addAll(
                cameraRotateX,
                cameraRotateY,
                cameraRotateZ,
                cameraTranslate);
        root.getChildren().add(camera);

        // Create Scene and Handlers
        createScene();
        Scene scene = new Scene(root, 800, 450, true);
        scene.setOnMousePressed((e) -> onMousePressed(e));
        scene.setOnMouseDragged((e) -> onMouseDragged(e));

        // Set the Stage
        stage.setTitle("Killer JavaFX - Checkers3D");
        stage.setScene(scene);
        scene.setFill(Color.LIGHTSKYBLUE);
        scene.setCamera(camera);
        stage.show();
    }

    public void onMousePressed(MouseEvent mouseEvent) {
        mouseOldX = mouseNewX = mouseEvent.getSceneX();
        mouseOldY = mouseNewY = mouseEvent.getSceneY();
    }

    public void onMouseDragged(MouseEvent mouseEvent) {
        mouseOldX = mouseNewX;
        mouseOldY = mouseNewY;
        mouseNewX = mouseEvent.getSceneX();
        mouseNewY = mouseEvent.getSceneY();

        double mouseDeltaX = (mouseNewX - mouseOldX);
        double mouseDeltaY = (mouseNewY - mouseOldY);

        cameraRotateX.setAngle(cameraRotateX.getAngle() - mouseDeltaY);
        cameraRotateY.setAngle(cameraRotateY.getAngle() + mouseDeltaX);
    }

    private void createScene() {
        lightScene();
        floatingSphere();
        root.getChildren().add(new CheckerFloor(20));
    }

    private void lightScene() {
        // Set up the ambient light
        //AmbientLight ambientLight = new AmbientLight(Color.DARKGRAY);

        // Set up the point lights
        PointLight pointLight1 = new PointLight(Color.WHITE);
        pointLight1.getTransforms().add(new Translate(-20, -20, -20));

        PointLight pointLight2 = new PointLight(Color.WHITE);
        pointLight2.getTransforms().add(new Translate(20, -20, 20));

        root.getChildren().addAll(pointLight1, pointLight2);
    }

    private void floatingSphere() {
        PhongMaterial material = new PhongMaterial();
        material.setDiffuseColor(Color.DODGERBLUE);
        material.setSpecularColor(Color.WHITE);

        Sphere sphere = new Sphere(2);
        sphere.getTransforms().add(new Translate(0, -4, 0));
        sphere.setMaterial(material);

        root.getChildren().add(sphere);
    }

}
CheckerFloor.java
package io.skidrunner.killer_javafx.ch15;

import javafx.geometry.Bounds;
import javafx.geometry.Point3D;
import javafx.geometry.VPos;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.SnapshotParameters;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.image.PixelReader;
import javafx.scene.image.PixelWriter;
import javafx.scene.image.WritableImage;
import javafx.scene.paint.Color;
import javafx.scene.paint.PhongMaterial;
import javafx.scene.shape.*;
import javafx.scene.text.Font;
import javafx.scene.text.FontWeight;
import javafx.scene.text.Text;
import javafx.scene.text.TextAlignment;
import javafx.scene.transform.Translate;

import java.util.ArrayList;

public class CheckerFloor extends Group {

    public CheckerFloor(int size) {
        super();

        if((size & 1) != 0) {
            throw new AssertionError("size should be multiple of 2");
        }
        ArrayList orangePoints = new ArrayList<>();
        ArrayList whitePoints = new ArrayList<>();
        for(int z = -size / 2; z <= (size / 2) - 1; z++) {
            boolean colorOrange = (z & 1) == 0;
            for(int x = -size / 2; x <= (size / 2) - 1; x++) {
                createPoints(x, 0,  z, colorOrange ? orangePoints : whitePoints);
                colorOrange = !colorOrange;
            }
        }
        getChildren().add(createMesh(orangePoints, Color.ORANGE));
        getChildren().add(createMesh(whitePoints, Color.WHITESMOKE));
        getChildren().add(createOriginMesh());
        getChildren().add(createLabelAxesGroup(size));
    }

    private void createPoints(int x, int y, int z, ArrayList points) {
        points.add(new Point3D(x, y, z + 1.0f));
        points.add(new Point3D(x + 1.0f, y, z + 1.0f));
        points.add(new Point3D(x + 1.0f, y, z));
        points.add( new Point3D(x, y, z));
    }

    private Shape3D createMesh(ArrayList points, Color color) {
        TriangleMesh mesh = new TriangleMesh(VertexFormat.POINT_NORMAL_TEXCOORD);
        for(int i = 0; i < points.size(); i += 4) {
            for(int j = 0; j < 4; j++) {
                Point3D point = points.get(i + j);
                mesh.getPoints().addAll((float)point.getX(), (float)point.getY(), (float)point.getZ());
            }
            mesh.getNormals().addAll(0,-1,0, 0,-1,0, 0,-1,0, 0,-1,0);
            mesh.getTexCoords().addAll(0,1, 1,1, 1,0, 0,0);

            int i0 = i;
            int i1 = i + 1;
            int i2 = i + 2;
            int i3 = i + 3;

            mesh.getFaces().addAll(i0,i0,i0, i3,i3,i3, i2,i2,i2);
            mesh.getFaces().addAll(i1,i1,i1, i0,i0,i0, i2,i2,i2);
        }

        PhongMaterial material = new PhongMaterial();
        material.setDiffuseColor(color);
        material.setSpecularColor(color.brighter());

        MeshView meshView = new MeshView(mesh);
        meshView.setMaterial(material);

        return meshView;
    }

    private Shape3D createOriginMesh() {
        PhongMaterial material = new PhongMaterial();
        material.setDiffuseColor(Color.DODGERBLUE);
        material.setSpecularColor(Color.WHITE);

        Box box = new Box(0.5, 0.1, 0.5);
        box.setMaterial(material);
        return box;
    }

    private Group createLabelAxesGroup(int size) {
        Group group = new Group();
        for (int i = -size / 2; i <= size / 2; i++) {
            Group marker = makeText(String.format("%02d", i));
            marker.getTransforms().add(new Translate(i, -0.5, 0));
            group.getChildren().add(marker);
        }
        for (int i = -size / 2; i <= size / 2; i++) {
            Group marker = makeText(String.format("%02d", i));
            marker.getTransforms().add(new Translate(0, -0.5, i));
            group.getChildren().add(marker);
        }
        return group;
    }

    private Group makeText(String string) {
        Font font = Font.font(null, FontWeight.BOLD, 64);
        Text text = new Text(string);
        text.setFont(font);
        new Scene(new Group(text));

        Bounds bounds = text.getLayoutBounds();

        Canvas canvas = new Canvas(bounds.getWidth() + 4, bounds.getHeight() + 4);
        GraphicsContext context = canvas.getGraphicsContext2D();
        context.setTextAlign(TextAlignment.CENTER);
        context.setTextBaseline(VPos.CENTER);
        context.setFill(Color.BLACK);
        context.fillRect(0, 0, canvas.getWidth(), canvas.getHeight());
        context.setFill(Color.WHITE);
        context.setFont(font);
        context.fillText(string, canvas.getWidth() * 0.5, canvas.getHeight() * 0.5);
        SnapshotParameters snapshotParameters = new SnapshotParameters();
        WritableImage writableImage = new WritableImage((int)canvas.getWidth(), (int)canvas.getHeight());
        WritableImage snapshot = canvas.snapshot(snapshotParameters, writableImage);
        PixelReader pixelReader = writableImage.getPixelReader();
        PixelWriter pixelWriter = writableImage.getPixelWriter();
        for(int y = 0; y < writableImage.getHeight(); y++) {
            for(int x = 0; x < writableImage.getWidth(); x++) {
                Color color = pixelReader.getColor(x, y).grayscale();
                pixelWriter.setColor(x, y, Color.DODGERBLUE.deriveColor(0, 1, 1, color.getBrightness()));
            }
        }
        PhongMaterial material = new PhongMaterial();
        material.setDiffuseMap(snapshot);
        material.setSelfIlluminationMap(snapshot);
        material.setSpecularMap(snapshot);

        float scale = (float)(0.5 / writableImage.getHeight());
        float extentX = (float)(writableImage.getWidth() * 0.5) * scale;
        float extentY = (float)writableImage.getHeight() * scale;

        TriangleMesh mesh = new TriangleMesh(VertexFormat.POINT_TEXCOORD);
        mesh.getPoints().addAll(-extentX,-extentY,0, extentX,-extentY,0, -extentX,0,0, extentX,0,0);
        mesh.getNormals().addAll(0,0,-1, 0,0,-1, 0,0,-1, 0,0,-1);
        mesh.getTexCoords().addAll(0,0, 1,0, 0,1, 1,1);
        mesh.getFaces().addAll(2,2, 1,1, 0,0, 2,2, 3,3, 1,1);

        MeshView meshView = new MeshView(mesh);
        meshView.setMaterial(material);

        //meshView.getTransforms().addAll(cameraRotateX, cameraRotateY,  cameraRotateZ);

        Group group = new Group();
        group.getChildren().add(meshView);

        return group;
    }
}

Comments

Popular Posts