Загрузка данных
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
public class Main extends JPanel implements ActionListener {
private static final int SCREEN_WIDTH = 640;
private static final int SCREEN_HEIGHT = 480;
private double posX = 2.5, posY = 2.5;
private double dirX = -1, dirY = 0;
private double planeX = 0, planeY = 0.66;
private boolean forward, backward, left, right;
private final int[][] map = {
{1,1,1,1,1,1,1,1},
{1,0,0,0,0,0,0,1},
{1,0,1,1,0,1,0,1},
{1,0,1,0,0,1,0,1},
{1,0,0,0,0,0,0,1},
{1,0,1,1,1,1,0,1},
{1,0,0,0,0,0,0,1},
{1,1,1,1,1,1,1,1}
};
public Main() {
setPreferredSize(new Dimension(SCREEN_WIDTH, SCREEN_HEIGHT));
setFocusable(true);
addKeyListener(new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) {
updateKeys(e.getKeyCode(), true);
}
@Override
public void keyReleased(KeyEvent e) {
updateKeys(e.getKeyCode(), false);
}
});
Timer timer = new Timer(16, this);
timer.start();
}
private void updateKeys(int code, boolean isPressed) {
if (code == KeyEvent.VK_W || code == KeyEvent.VK_UP) forward = isPressed;
if (code == KeyEvent.VK_S || code == KeyEvent.VK_DOWN) backward = isPressed;
if (code == KeyEvent.VK_A || code == KeyEvent.VK_LEFT) left = isPressed;
if (code == KeyEvent.VK_D || code == KeyEvent.VK_RIGHT) right = isPressed;
}
@Override
public void actionPerformed(ActionEvent e) {
double moveSpeed = 0.05;
double rotSpeed = 0.04;
if (forward) {
if (map[(int)(posX + dirX * moveSpeed)][(int)posY] == 0) posX += dirX * moveSpeed;
if (map[(int)posX][(int)(posY + dirY * moveSpeed)] == 0) posY += dirY * moveSpeed;
}
if (backward) {
if (map[(int)(posX - dirX * moveSpeed)][(int)posY] == 0) posX -= dirX * moveSpeed;
if (map[(int)posX][(int)(posY - dirY * moveSpeed)] == 0) posY -= dirY * moveSpeed;
}
if (right) {
double oldDirX = dirX;
dirX = dirX * Math.cos(-rotSpeed) - dirY * Math.sin(-rotSpeed);
dirY = oldDirX * Math.sin(-rotSpeed) + dirY * Math.cos(-rotSpeed);
double oldPlaneX = planeX;
planeX = planeX * Math.cos(-rotSpeed) - planeY * Math.sin(-rotSpeed);
planeY = oldPlaneX * Math.sin(-rotSpeed) + planeY * Math.cos(-rotSpeed);
}
if (left) {
double oldDirX = dirX;
dirX = dirX * Math.cos(rotSpeed) - dirY * Math.sin(rotSpeed);
dirY = oldDirX * Math.sin(rotSpeed) + dirY * Math.cos(rotSpeed);
double oldPlaneX = planeX;
planeX = planeX * Math.cos(rotSpeed) - planeY * Math.sin(rotSpeed);
planeY = oldPlaneX * Math.sin(rotSpeed) + planeY * Math.cos(rotSpeed);
}
repaint();
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(new Color(50, 50, 50));
g.fillRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT / 2);
g.setColor(new Color(100, 100, 100));
g.fillRect(0, SCREEN_HEIGHT / 2, SCREEN_WIDTH, SCREEN_HEIGHT / 2);
for (int x = 0; x < SCREEN_WIDTH; x++) {
double cameraX = 2 * x / (double) SCREEN_WIDTH - 1;
double rayDirX = dirX + planeX * cameraX;
double rayDirY = dirY + planeY * cameraX;
int mapX = (int) posX;
int mapY = (int) posY;
double sideDistX;
double sideDistY;
double deltaDistX = (rayDirX == 0) ? 1e30 : Math.abs(1 / rayDirX);
double deltaDistY = (rayDirY == 0) ? 1e30 : Math.abs(1 / rayDirY);
double perpWallDist;
int stepX;
int stepY;
int hit = 0;
int side = 0;
if (rayDirX < 0) {
stepX = -1;
sideDistX = (posX - mapX) * deltaDistX;
} else {
stepX = 1;
sideDistX = (mapX + 1.0 - posX) * deltaDistX;
}
if (rayDirY < 0) {
stepY = -1;
sideDistY = (posY - mapY) * deltaDistY;
} else {
stepY = 1;
sideDistY = (mapY + 1.0 - posY) * deltaDistY;
}
while (hit == 0) {
if (sideDistX < sideDistY) {
sideDistX += deltaDistX;
mapX += stepX;
side = 0;
} else {
sideDistY += deltaDistY;
mapY += stepY;
side = 1;
}
if (map[mapX][mapY] > 0) hit = 1;
}
if (side == 0) perpWallDist = (sideDistX - deltaDistX);
else perpWallDist = (sideDistY - deltaDistY);
int lineHeight = (int) (SCREEN_HEIGHT / perpWallDist);
int drawStart = -lineHeight / 2 + SCREEN_HEIGHT / 2;
if (drawStart < 0) drawStart = 0;
int drawEnd = lineHeight / 2 + SCREEN_HEIGHT / 2;
if (drawEnd >= SCREEN_HEIGHT) drawEnd = SCREEN_HEIGHT - 1;
if (side == 1) g.setColor(new Color(180, 0, 0));
else g.setColor(new Color(220, 0, 0));
g.drawLine(x, drawStart, x, drawEnd);
}
}
public static void main(String[] args) {
JFrame frame = new JFrame("3D Raycaster");
Main panel = new Main();
frame.add(panel);
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setResizable(false);
frame.setVisible(true);
}
}