Advertisement
mrlolthe1st

Untitled

Aug 23rd, 2021
1,297
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 10.14 KB | None | 0 0
  1. import javax.swing.*;
  2. import java.awt.*;
  3. import java.awt.event.ActionEvent;
  4. import java.awt.event.ActionListener;
  5. import java.awt.event.KeyEvent;
  6. import java.awt.event.KeyListener;
  7. import java.awt.image.BufferStrategy;
  8. import java.awt.image.BufferedImage;
  9. import java.awt.image.DataBufferInt;
  10. import java.io.File;
  11. import java.util.ArrayList;
  12. import java.util.Random;
  13. import javax.imageio.ImageIO;
  14.  
  15. public class Main implements Runnable {
  16.     final int WIDTH = 1024, HEIGHT = 768;
  17.     final double ROT_SHIFT = 0.007;
  18.     final String TITLE = "Pseudo-3D";
  19.     JFrame frame;
  20.     Canvas canvas;
  21.     BufferedImage screenBuffer;
  22.  
  23.     Thread t;
  24.     boolean running;
  25.  
  26.     int[] screen;
  27.     Graph graphics;
  28.     double rot = 0;
  29.     double posX = 0, posY = 0;
  30.  
  31.     public void run() {
  32.         graphics = new Graph(WIDTH, HEIGHT);
  33.         while (running) {
  34.             graphics.draw(rot, posX, posY);
  35.  
  36.             // Скопируем отрендеренное изображение
  37.             System.arraycopy(graphics.pixels, 0, screen, 0, WIDTH * HEIGHT);
  38.  
  39.             // Отрисуем буфер на экран
  40.             BufferStrategy bs = canvas.getBufferStrategy();
  41.             Graphics g = bs.getDrawGraphics();
  42.             g.drawImage(screenBuffer, 0, 0, WIDTH, HEIGHT, null);
  43.             g.dispose();
  44.             bs.show();
  45.         }
  46.     }
  47.     public Main() {
  48.         running = false;
  49.         frame = new JFrame();
  50.         canvas = new Canvas();
  51.         frame.add(canvas);
  52.         frame.pack();
  53.         canvas.addKeyListener(new KeyListener() {
  54.  
  55.             @Override
  56.             public void keyTyped(KeyEvent e) {
  57.  
  58.             }
  59.  
  60.             @Override
  61.             public void keyPressed(KeyEvent e) {
  62.                 switch (e.getKeyCode()) {
  63.                     case KeyEvent.VK_LEFT: rot -= ROT_SHIFT; break;
  64.                     case KeyEvent.VK_RIGHT: rot += ROT_SHIFT; break;
  65.                     case KeyEvent.VK_W:
  66.                         posX += Math.cos(rot);
  67.                         posY += Math.sin(rot);
  68.                         break;
  69.                     case KeyEvent.VK_A:
  70.                         posY -= Math.cos(rot);
  71.                         posX += Math.sin(rot);
  72.                         break;
  73.                     case KeyEvent.VK_S:
  74.                         posX -= Math.cos(rot);
  75.                         posY -= Math.sin(rot);
  76.                         break;
  77.                     case KeyEvent.VK_D:
  78.                         posY += Math.cos(rot);
  79.                         posX -= Math.sin(rot);
  80.                         break;
  81.                 }
  82.             }
  83.  
  84.             @Override
  85.             public void keyReleased(KeyEvent e) {
  86.  
  87.             }
  88.         });
  89.         frame.setFocusable(true);
  90.         frame.setFocusTraversalKeysEnabled(false);
  91.         frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  92.         frame.setSize(WIDTH, HEIGHT);
  93.         frame.setResizable(false);
  94.         frame.setLocationRelativeTo(null);
  95.         frame.setTitle(TITLE);
  96.         frame.setVisible(true);
  97.         canvas.createBufferStrategy(3);
  98.         screenBuffer = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
  99.         screen = ((DataBufferInt)screenBuffer.getRaster().getDataBuffer()).getData();
  100.         running = true;
  101.         t = new Thread(this);
  102.         t.start();
  103.     }
  104.  
  105.     public static void main(String[] args) {
  106.         new Main();
  107.     }
  108.  
  109.  
  110.     // Стена с началом в (x, z) и концом в (xRight, z)
  111.     private class Wall {
  112.         public double x, z, xRight;
  113.         public Wall(double a, double b, double xEnd) {
  114.             x = a;
  115.             z = b;
  116.             xRight = xEnd;
  117.         }
  118.     }
  119.  
  120.     private class Graph {
  121.         int width, height, imageWidth, imageHeight;
  122.         public int[] pixels;
  123.         ArrayList<Wall> walls;
  124.         double imageScale = 0, stepScale = 0;
  125.         BufferedImage img;
  126.         public Graph(int width, int height) {
  127.             pixels = new int[width * height];
  128.             this.width = width;
  129.             this.height = height;
  130.             try {
  131.                 img = ImageIO.read(new File("C:\\Work\\1.bmp"));
  132.             } catch (Exception e) {
  133.                 e.printStackTrace();
  134.             }
  135.             walls = new ArrayList<Wall>();
  136.             walls.add(new Wall(-1, 6, 1));
  137.             imageWidth = img.getWidth();
  138.             imageHeight = img.getHeight();
  139.             imageScale = Math.sqrt(imageWidth * imageHeight);
  140.             stepScale = Math.sqrt(imageWidth * imageHeight) / 20.;
  141.         }
  142.  
  143.         void draw(double rot, double posX, double posY) {
  144.             posX *= stepScale;
  145.             posY *= stepScale;
  146.             // Тут начинается магия
  147.             double _cos = Math.cos(rot), _sin = Math.sin(rot);
  148.  
  149.             for (int y = 0; y < height; ++y) {
  150.                 // https://www.wolframalpha.com/input/?i=%28y-384%29%2F384
  151.                 double ceiling = Math.abs((y - height / 2.) / height);
  152.                 // Тут отображаем "глубину" относительно y
  153.                 // https://www.wolframalpha.com/input/?i=1%2F%28%28y-384%29%2F384%29
  154.                 double z = imageScale * Math.abs(height / (y - height / 2.));
  155.                 double brightness = 1;
  156.  
  157.                 if (Math.abs(y - height/ 2) < 100.) {
  158.                     // Обрежем вид относительно дальности: (|y-height/2|/80)^2
  159.                     // На выходе - коэффициент "светлости" (brightness) пикселя
  160.                     // можно попробовать поэксперементировать с
  161.                     // логарифмированием этой штуки и выбрать вариант,
  162.                     // более приятный глазу.
  163.                     brightness = Math.abs(y - height / 2.) / 100.;
  164.                     brightness *= brightness * brightness;
  165.                 }
  166.  
  167.                 for (int x = 0; x < width; ++x) {
  168.                     double depth = (x - width / 2.) * Math.abs(imageScale / (y - height / 2.));
  169.                     // https://www.wolframalpha.com/input/?i=1%2F%28%28y-384%29%2F384%29+*+%28x+-+512%29%2F512
  170.                     // можно посмотреть на график тут. Мы его "примерно" отображаем на наш экран
  171.                     // Высчитываем a и b - координаты в картинке, которая заливает пол и потолок
  172.                     //System.out.println(z);
  173.                     int a = Math.abs((int)(depth * _cos + z * _sin + posY)) % (imageWidth);
  174.                     int b = Math.abs(((int)(z * _cos - depth * _sin + posX))) % (imageHeight);
  175.                     //pixels[x + y * width] = a;
  176.                     int rgb = img.getRGB(a, b);
  177.                     // Домножим каждую компоненту цвета на яркость
  178.                     rgb = ((int)((rgb & 0xFF) * brightness)) | ((int)(((rgb & 0xFF00) >> 8) * brightness)) << 8
  179.                             | ((int)(((rgb & 0xFF0000) >> 16) * brightness)) << 16;
  180.                     pixels[x + y * width] = rgb;
  181.                 }
  182.             }
  183.             drawWalls(rot, posX, posY);
  184.         }
  185.  
  186.         void drawWalls(double rot, double posX, double posY) {
  187.             posX /= stepScale;
  188.             posY /= stepScale;
  189.             double _cos = Math.cos(rot), _sin = Math.sin(rot);
  190.             Random r = new Random();
  191.             for (int i = 0; i < walls.size(); ++i) {
  192.                 Wall w = walls.get(i);
  193.                 double xLeft = w.x * 20;
  194.                 double xRight = w.xRight * 20;
  195.                 double zDistance = w.z * 20;
  196.                 double yHeight = 40; // 2 блока
  197.  
  198.                 double xcLeft = (xLeft - posY) * 2;
  199.                 double zcLeft = (zDistance - posX) * 2;
  200.  
  201.                 double rotLeftSideX = _cos * xcLeft - _sin * zcLeft;
  202.                 double yCornerTL = -yHeight;
  203.                 double yCornerBL = (yHeight);
  204.                 double rotLeftSideZ = _cos * zcLeft + _sin * xcLeft;
  205.  
  206.                 double xcRight = (xRight - posY) * 2;
  207.                 double zcRight = (zDistance - posX) * 2;
  208.  
  209.                 double rotRightSideX = xcRight * _cos - zcRight * _sin;
  210.                 double yCornerTR = (-yHeight);
  211.                 double yCornerBR = (yHeight);
  212.                 double rotRightSideZ = zcRight * _cos + xcRight * _sin;
  213.  
  214.                 double xPixelLeft = rotLeftSideX / rotLeftSideZ * height + width / 2;
  215.                 double xPixelRight = (rotRightSideX / rotRightSideZ * height + width / 2);
  216.  
  217.                 if (xPixelLeft >= xPixelRight) {
  218.                     return;
  219.                 }
  220.  
  221.                 int xPixelLeftInt = (int)(xPixelLeft);
  222.                 int xPixelRightInt = (int)(xPixelRight);
  223.                 xPixelLeftInt = Math.max(0, xPixelLeftInt);
  224.                 xPixelRightInt = Math.min(width, xPixelRightInt);
  225.                 double yPixelLeftTop = (int) (yCornerTL / rotLeftSideZ * height + height / 2);
  226.                 double yPixelLeftBottom = (int) (yCornerBL / rotLeftSideZ * height + height / 2);
  227.                 double yPixelRightTop = (int) (yCornerTR / rotRightSideZ * height + height / 2);
  228.                 double yPixelRightBottom = (int) (yCornerBR / rotRightSideZ * height + height / 2);
  229.                 //System.out.println(rotLeftSideX + " " +rotLeftSideZ+ " " +xPixelLeft + " " + xPixelRight);
  230.                 for (int x = xPixelLeftInt; x < xPixelRightInt; ++x) {
  231.                     double pixelRotation = (x - xPixelLeft) / (xPixelRight - xPixelLeft);
  232.                     double yPixelTop = Math.max(0, yPixelLeftTop + (yPixelRightTop - yPixelLeftTop) * pixelRotation);
  233.                     double yPixelBottom = Math.min(height, yPixelLeftBottom + (yPixelRightBottom - yPixelLeftBottom) * pixelRotation);
  234.                     //System.out.println(yPixelBottom - yPixelTop);
  235.                     for (int y = (int) yPixelTop; y < yPixelBottom; ++y) {
  236.                         pixels[x + y * width] = 0xAAAAAA;
  237.                     }
  238.                 }
  239.             }
  240.         }
  241.     }
  242. }
  243.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement