aboutsummaryrefslogtreecommitdiff
path: root/Занимательное программирование/4/5_3d/src/main/java/net/caraus/labyrinth/Main.java
blob: 35a6c014f5210fc70cd1db507c5333911713865b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
package net.caraus.labyrinth;

import com.badlogic.gdx.ApplicationListener;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.GL32;
import com.badlogic.gdx.graphics.PerspectiveCamera;
import com.badlogic.gdx.graphics.VertexAttributes.Usage;
import com.badlogic.gdx.graphics.g3d.Material;
import com.badlogic.gdx.graphics.g3d.Model;
import com.badlogic.gdx.graphics.g3d.ModelBatch;
import com.badlogic.gdx.graphics.g3d.ModelInstance;
import com.badlogic.gdx.graphics.g3d.attributes.BlendingAttribute;
import com.badlogic.gdx.graphics.g3d.attributes.ColorAttribute;
import com.badlogic.gdx.graphics.g3d.utils.MeshPartBuilder;
import com.badlogic.gdx.graphics.g3d.utils.ModelBuilder;
import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
import static com.badlogic.gdx.graphics.glutils.ShapeRenderer.ShapeType;
import com.badlogic.gdx.math.Vector3;
import com.badlogic.gdx.utils.ScreenUtils;

public class Main implements ApplicationListener {

    public ModelBatch modelBatch;
    public Model model;
    public ModelInstance instance;
    public MazeInputProcessor camController;
    public ShapeRenderer shapeRenderer;
    public Maze maze;

    private static final float WALL_SIZE = 5;

    @Override
    public void create() {
        this.modelBatch = new ModelBatch();
        this.shapeRenderer = new ShapeRenderer();
        var cam = new PerspectiveCamera(67, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());

        cam.position.set(0f, 0f, 0f);
        cam.lookAt(0, WALL_SIZE, 0);
        cam.near = 1f;
        cam.far = 300f;
        cam.update();

        this.maze = new KruskalMaze(15, 9).generate();
        this.camController = new MazeInputProcessor(this.maze, cam, WALL_SIZE);
        Gdx.input.setInputProcessor(camController);

        ModelBuilder worldBuilder = new ModelBuilder();
        worldBuilder.begin();

        for (var x = 0; x < this.maze.width(); ++x) {
            for (var y = 0; y < this.maze.height(); ++y) {
                buildLocation(worldBuilder, x, y);
            }
            buildLocation(worldBuilder, new Location(false, true),
                    new Vector3(x * WALL_SIZE * 2, this.maze.height() * WALL_SIZE * 2, 0),
                    String.format("lx%dy%d", x, this.maze.height()));
        }
        for (var y = 0; y < this.maze.height(); ++y) {
            buildLocation(worldBuilder, new Location(true, false),
                    new Vector3(this.maze.width() * WALL_SIZE * 2, y * WALL_SIZE * 2, 0),
                    String.format("lx%dy%d", this.maze.width(), y));
        }
        buildFloor(worldBuilder);
        this.model = worldBuilder.end();
        this.instance = new ModelInstance(this.model);
    }

    private static Vector3 makeTranslation(int x, int y) {
        return new Vector3(x * WALL_SIZE * 2, y * WALL_SIZE * 2, 0);
    }

    // Пол.
    private void buildFloor(ModelBuilder worldBuilder) {
        MeshPartBuilder meshBuilder = worldBuilder.part("floor",
                GL32.GL_TRIANGLES, Usage.Position | Usage.Normal,
                new Material(ColorAttribute.createDiffuse(Color.ORANGE)));

        var farX = -WALL_SIZE + this.maze.width() * WALL_SIZE * 2;
        var farY = -WALL_SIZE + this.maze.height() * WALL_SIZE * 2;

        meshBuilder.rect(new MeshPartBuilder.VertexInfo().setPos(-WALL_SIZE, -WALL_SIZE, -WALL_SIZE),
                new MeshPartBuilder.VertexInfo().setPos(farX, -WALL_SIZE, -WALL_SIZE),
                new MeshPartBuilder.VertexInfo().setPos(farX, farY, -WALL_SIZE),
                new MeshPartBuilder.VertexInfo().setPos(-WALL_SIZE, farY, -WALL_SIZE));
    }

    private static void buildLocation(ModelBuilder worldBuilder,
            Location builtLocation, Vector3 translation, String partName) {
        var corner00 = new Vector3();
        var corner10 = new Vector3();
        var corner11 = new Vector3();
        var corner01 = new Vector3();

        MeshPartBuilder meshBuilder = worldBuilder.part(partName,
                GL32.GL_TRIANGLES, Usage.Position | Usage.Normal, new Material(new BlendingAttribute(0.9f)));

        if (builtLocation.leftWall()) {
            meshBuilder.rect(corner00.set(-WALL_SIZE, -WALL_SIZE, -WALL_SIZE).add(translation),
                    corner10.set(-WALL_SIZE, WALL_SIZE, -WALL_SIZE).add(translation),
                    corner11.set(-WALL_SIZE, WALL_SIZE, WALL_SIZE).add(translation),
                    corner01.set(-WALL_SIZE, -WALL_SIZE, WALL_SIZE).add(translation),
                    null);
            meshBuilder.rect(corner01.set(-WALL_SIZE, -WALL_SIZE, WALL_SIZE).add(translation),
                    corner11.set(-WALL_SIZE, WALL_SIZE, WALL_SIZE).add(translation),
                    corner10.set(-WALL_SIZE, WALL_SIZE, -WALL_SIZE).add(translation),
                    corner00.set(-WALL_SIZE, -WALL_SIZE, -WALL_SIZE).add(translation),
                    null);
        }
        if (builtLocation.upWall()) {
            meshBuilder.rect(corner00.set(-WALL_SIZE, -WALL_SIZE, -WALL_SIZE).add(translation),
                    corner10.set(WALL_SIZE, -WALL_SIZE, -WALL_SIZE).add(translation),
                    corner11.set(WALL_SIZE, -WALL_SIZE, WALL_SIZE).add(translation),
                    corner01.set(-WALL_SIZE, -WALL_SIZE, WALL_SIZE).add(translation),
                    null);
            meshBuilder.rect(corner01.set(-WALL_SIZE, -WALL_SIZE, WALL_SIZE).add(translation),
                    corner11.set(WALL_SIZE, -WALL_SIZE, WALL_SIZE).add(translation),
                    corner10.set(WALL_SIZE, -WALL_SIZE, -WALL_SIZE).add(translation),
                    corner00.set(-WALL_SIZE, -WALL_SIZE, -WALL_SIZE).add(translation),
                    null);
        }
    }

    private void buildLocation(ModelBuilder worldBuilder, int x, int y) {
        var translation = new Vector3(x * WALL_SIZE * 2, y * WALL_SIZE * 2, 0);

        buildLocation(worldBuilder, this.maze.at(x, y), translation, String.format("lx%dy%d", x, y));
    }

    @Override
    public void render() {
        this.camController.update();

        Gdx.gl.glClear(GL32.GL_COLOR_BUFFER_BIT | GL32.GL_DEPTH_BUFFER_BIT);
        ScreenUtils.clear(0.15f, 0.15f, 0.2f, 1f);

        Gdx.gl.glViewport(0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
        this.modelBatch.begin(this.camController.getCamera());
        this.modelBatch.render(this.instance);
        this.modelBatch.end();

        this.shapeRenderer.begin(ShapeType.Line);
        this.shapeRenderer.setColor(Color.BLUE);
        this.maze.draw(this.shapeRenderer);
        this.shapeRenderer.end();
    }

    @Override
    public void dispose() {
        this.modelBatch.dispose();
        this.model.dispose();
        this.shapeRenderer.dispose();
    }

    @Override
    public void resume() {
    }

    @Override
    public void resize(int width, int height) {
    }

    @Override
    public void pause() {
    }
}