有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

多边形如何在Java中绘制像素完美的旋转矩形?

我试图为游戏的扩展实现一个滚动角度,为了模拟它,我最好的方法是围绕屏幕中心旋转矩形

问题是,当我用一个简单的旋转函数旋转矩形时,会出现黑色条纹(注意,我使用的是缓冲策略)

截图

enter image description here

这是旋转函数:

public void rot(int ai[], int ai1[], int i, int j, int k, int l)
{
    if(k != 0)
    {
        for(int i1 = 0; i1 < l; i1++)
        {
            int j1 = ai[i1];
            int k1 = ai1[i1];
            ai[i1] = i + (int)((float)(j1 - i) * cos(k) - (float)(k1 - j) * sin(k));
            ai1[i1] = j + (int)((float)(j1 - i) * sin(k) + (float)(k1 - j) * cos(k));
        }

    }
}
  • ai[]=x坐标
  • ai1[]=y坐标
  • i=x-旋转中心点
  • j=y-旋转中心点
  • k=旋转角度
  • l=两个数组的长度

请注意,矩形数据以连续形式存储

例如:第一个矩形的y坐标为[0,0,100,100],第二个矩形的y坐标为[100,100,200,200],依此类推

我不想使用图形2D。rotate(),因为这会对我的目的造成太多的质量影响,抗锯齿只会产生相同的条纹,但它们看起来更平滑

我该怎么办

编辑:提供的测试代码

主要类别:

import java.awt.Canvas;
import java.awt.Dimension;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.image.BufferStrategy;

import javax.swing.JOptionPane;

class ReplayViewer extends Canvas implements Runnable
{
    private static final long serialVersionUID = 355508539070062621L;
    private static boolean running = false;
    private Thread thread;
    private Graphics g;
    private BufferStrategy bs;

    Medium medium;

    private synchronized void start()
    {
        if(running)
            return;

        createBufferStrategy(3);
        bs = this.getBufferStrategy();

        g = bs.getDrawGraphics();

        running = true;
        thread = new Thread(this);
        thread.start();
    }

    private synchronized void stop()
    {
        try
        {
            thread.join();
            g.dispose();
        }catch (InterruptedException e)
        {
            e.printStackTrace();
        }
    }

    public void run() 
    {   
        long lastTime = System.nanoTime();
        final float numOfTicks = 30F;
        float ns = 1000000000 / numOfTicks;
        double delta = 0;

        while(running)
        {
            long now = System.nanoTime();
            delta += (now - lastTime) / ns;
            lastTime = now;

            if (delta >= 1)
            {
                updateGameState();
                drawToScreen();
                try
                {
                    Thread.sleep(10);
                } catch (InterruptedException e)
                {
                    e.printStackTrace();
                }
                delta--;
            }
        }
        stop();
    }

    private void updateGameState()
    {

    }

    private void drawToScreen()
    {
        medium.d(g);
        bs.show();
    }

    public ReplayViewer()
    {
        medium = new Medium();
        setPreferredSize(new Dimension(medium.w, medium.h));
    }

    public static void main(String[] args)
    {
        try
        {
            final Frame frame = new Frame("NFM Replay Viewer");
            ReplayViewer rply = new ReplayViewer();

            frame.add(rply);
            frame.setResizable(false);
            frame.pack();
            frame.setLocationRelativeTo(null);
            frame.setVisible(true);

            frame.addWindowListener(new WindowAdapter() 
            {
                public void windowClosing(WindowEvent we)
                {
                    running = false;
                    frame.setVisible(false);
                    frame.dispose();
                    System.exit(0);
                }
            });

            rply.start();

        } catch (Exception e)
        {
            e.printStackTrace();
            JOptionPane.showMessageDialog(null, "Viewer cannot be open!", "Error", 0);
        }
    }
}

中级:

import java.awt.Color;
import java.awt.Graphics;

public class Medium
{
    int focus_point;
    int ground;
    int skyline;
    int fade[] = { 3000, 4500, 6000, 7500, 9000, 10500, 12000, 13500, 15000, 16500, 18000, 19500, 21000, 22500, 24000, 25500 };
    int cldd[] = { 210, 210, 210, 1, -1000 };
    int clds[] = { 210, 210, 210 };
    int osky[] = { 170, 220, 255 };
    int csky[] = { 170, 220, 255 };
    int ogrnd[] = { 205, 200, 200 };
    int cgrnd[] = { 205, 200, 200 };
    int texture[] = { 0, 0, 0, 50 };
    int cpol[] = { 215, 210, 210 };
    int crgrnd[] = { 205, 200, 200 };
    int cfade[] = { 255, 220, 220 };
    int snap[] = { 0, 0, 0 };
    int fogd;
    boolean loadnew;
    boolean lightson;
    boolean darksky;
    int lightn;
    int lilo;
    boolean lton;
    int noelec;
    int trk;
    boolean crs;
    int cx;
    int cy;
    int cz;
    int xz;
    int zy;
    int x;
    int y;
    int z;
    int iw;
    int ih;
    int w;
    int h;
    int nsp;
    int spx[];
    int spz[];
    int sprad[];
    int adv;
    float tcos[];
    float tsin[];
    int lastmaf;
    int checkpoint;
    boolean lastcheck;
    float elecr;
    boolean cpflik;
    boolean nochekflk;
    int cntrn;
    boolean diup[] = { false, false, false };
    int rand[] = { 0, 0, 0 };
    int trn;
    int hit;
    int ogpx[][];
    int ogpz[][];
    float pvr[][];
    int cgpx[];
    int cgpz[];
    int pmx[];
    float pcv[];
    int sgpx;
    int sgpz;
    int nrw;
    int ncl;
    int noc;
    int clx[];
    int clz[];
    int cmx[];
    int clax[][][];
    int clay[][][];
    int claz[][][];
    int clc[][][][];
    int nmt;
    int mrd[];
    int nmv[];
    int mtx[][];
    int mty[][];
    int mtz[][];
    int mtc[][][];
    int nst;
    int stx[];
    int stz[];
    int stc[][][];
    boolean bst[];
    int twn[];
    int resdown;
    int xy;

    public float sin(int i)
    {
        for(; i >= 360; i -= 360) { }
        for(; i < 0; i += 360) { }
        return tsin[i];
    }

    public float cos(int i)
    {
        for(; i >= 360; i -= 360) { }
        for(; i < 0; i += 360) { }
        return tcos[i];
    }

    public int ys(int i, int j) 
    {
        if (j < 10)
            j = 10;
        return ((j - focus_point) * (cy - i)) / j + i;
    }

    public void d(Graphics graphics2d)
    {
        nsp = 0;
        int loops = 0;
        if (xz > 360)
        {
            xz -= 360;
        }
        if (xz < 0)
        {
            xz += 360;
        }
        for(; zy >= 90; zy -= 180) { loops++; }
        for(; zy < -90; zy += 180) { loops--; }
        ground = 250 - y;
        int ai[] = new int[4];
        int ai1[] = new int[4];
        int i = cgrnd[0];
        int j = cgrnd[1];
        int k = cgrnd[2];
        int l = crgrnd[0];
        int i1 = crgrnd[1];
        int j1 = crgrnd[2];
        int k1;

        if(loops % 2 == 0)
            k1 = h + cx;
        else
            k1 = ih - cx;

        for (int l1 = 0; l1 < 16; l1++)
        {
            int j2 = fade[l1];
            int l2;

            if(loops % 2 == 0)
            {
                l2 = ground;
                if (zy != 0)
                {
                    l2 = cy + (int) ((ground - cy) * cos(zy) - (fade[l1] - cz) * sin(zy));
                    j2 = cz + (int) ((ground - cy) * sin(zy) + (fade[l1] - cz) * cos(zy));
                }
            } else
            {
                l2 = -ground + h;
                if(zy != 0)
                {
                    l2 = cy + (int)((float)(-ground + h - cy) * cos(zy) - (float)(fade[l1] - cz) * sin(zy));
                    j2 = cz + (int)((float)(-ground + h - cy) * sin(zy) + (float)(fade[l1] - cz) * cos(zy));
                }
            }
            ai[0] = iw;
            ai1[0] = ys(l2, j2);
            if (ai1[0] < ih - cx)
            {
                ai1[0] = ih - cx;
            }
            if (ai1[0] > h + cx)
            {
                ai1[0] = h + cx;
            }
            ai[1] = iw - cx;
            ai1[1] = k1;
            ai[2] = w + cx;
            ai1[2] = k1;
            ai[3] = w + cx;
            ai1[3] = ai1[0];
            k1 = ai1[0];
            if (l1 > 0)
            {
                l = (l * 7 + cfade[0]) / 8;
                i1 = (i1 * 7 + cfade[1]) / 8;
                j1 = (j1 * 7 + cfade[2]) / 8;
                if (l1 < 3)
                {
                    i = (i * 7 + cfade[0]) / 8;
                    j = (j * 7 + cfade[1]) / 8;
                    k = (k * 7 + cfade[2]) / 8;
                } else
                {
                    i = l;
                    j = i1;
                    k = j1;
                }
            }
            rot(ai, ai1, cx, cy, xy, 4);
            graphics2d.setColor(new Color(i, j, k));
            graphics2d.fillPolygon(ai, ai1, 4);
        }
        if (lightn != -1 && lton)
        {
            if (lightn < 16)
            {
                if (lilo > lightn + 217)
                {
                    lilo -= 3;
                } else
                {
                    lightn = (int) (16F + 16F * random());
                }
            } else if (lilo < lightn + 217)
            {
                lilo += 7;
            } else
            {
                lightn = (int) (16F * random());
            }
            csky[0] = (int) (lilo + lilo * (snap[0] / 100F));
            if (csky[0] > 255)
            {
                csky[0] = 255;
            }
            if (csky[0] < 0)
            {
                csky[0] = 0;
            }
            csky[1] = (int) (lilo + lilo * (snap[1] / 100F));
            if (csky[1] > 255)
            {
                csky[1] = 255;
            }
            if (csky[1] < 0)
            {
                csky[1] = 0;
            }
            csky[2] = (int) (lilo + lilo * (snap[2] / 100F));
            if (csky[2] > 255)
            {
                csky[2] = 255;
            }
            if (csky[2] < 0)
            {
                csky[2] = 0;
            }
        }
        i = csky[0];
        j = csky[1];
        k = csky[2];
        int i2 = i;
        int k2 = j;
        int i3 = k;

        int j3;
        int k3;

        if(loops % 2 == 0)
        {
            j3 = cy + (int) ((skyline - 700 - cy) * cos(zy) - (7000 - cz) * sin(zy));
            k3 = cz + (int) ((skyline - 700 - cy) * sin(zy) + (7000 - cz) * cos(zy));
        } else
        {
            j3 = cy + (int) ((-skyline + 700 + h - cy) * cos(zy) - (7000 - cz) * sin(zy));
            k3 = cz + (int) ((-skyline + 700 + h - cy) * sin(zy) + (7000 - cz) * cos(zy));
        }

        j3 = ys(j3, k3);

        int l3;

        if(loops % 2 == 0)
            l3 = ih - cx;
        else
            l3 = h + cx;

        for (int i4 = 0; i4 < 16; i4++)
        {
            int k4 = fade[i4];
            int i5;

            if (loops % 2 == 0)
            {
                i5 = skyline;
                if (zy != 0)
                {
                    i5 = cy + (int) ((skyline - cy) * cos(zy) - (fade[i4] - cz) * sin(zy));
                    k4 = cz + (int) ((skyline - cy) * sin(zy) + (fade[i4] - cz) * cos(zy));
                }
            } else
            {
                i5 = -skyline + h;
                if (zy != 0)
                {
                    i5 = cy + (int) ((-skyline + h - cy) * cos(zy) - (fade[i4] - cz) * sin(zy));
                    k4 = cz + (int) ((-skyline + h - cy) * sin(zy) + (fade[i4] - cz) * cos(zy));
                }
            }

            ai[0] = iw - cx;
            ai1[0] = ys(i5, k4);
            if (ai1[0] < ih - cx)
            {
                ai1[0] = ih - cx;
            }
            if (ai1[0] > h + cx)
            {
                ai1[0] = h + cx;
            }
            ai[1] = iw - cx;
            ai1[1] = l3;
            ai[2] = w + cx;
            ai1[2] = l3;
            ai[3] = w + cx;
            ai1[3] = ai1[0];
            l3 = ai1[0];
            if (i4 > 0)
            {
                i = (i * 7 + cfade[0]) / 8;
                j = (j * 7 + cfade[1]) / 8;
                k = (k * 7 + cfade[2]) / 8;
            }
            rot(ai, ai1, cx, cy, xy, 4);
            graphics2d.setColor(new Color(i, j, k));
            graphics2d.fillPolygon(ai, ai1, 4);
        }
        ai[0] = iw - cx;
        ai1[0] = l3;
        ai[1] = iw - cx;
        ai1[1] = k1;
        ai[2] = w + cx;
        ai1[2] = k1;
        ai[3] = w + cx;
        ai1[3] = l3;

        float f = (Math.abs(y) - 250F) / (fade[0] * 2);
        if (f < 0.0F)
        {
            f = 0.0F;
        }
        if (f > 1.0F)
        {
            f = 1.0F;
        }
        i = (int) ((i * (1.0F - f) + l * (1.0F + f)) / 2.0F);
        j = (int) ((j * (1.0F - f) + i1 * (1.0F + f)) / 2.0F);
        k = (int) ((k * (1.0F - f) + j1 * (1.0F + f)) / 2.0F);
        rot(ai, ai1, cx, cy, xy, 4);
        graphics2d.setColor(new Color(i, j, k));
        graphics2d.fillPolygon(ai, ai1, 4);

        if (resdown != 2)
        {
            for (int j4 = 1; j4 < 20; j4++)
            {
                int l4 = 7000;
                int j5;

                if (loops % 2 == 0)
                {
                    j5 = skyline - 700 - j4 * 70;
                    if (zy != 0 && j4 != 19)
                    {
                        j5 = cy + (int) ((skyline - 700 - j4 * 70 - cy) * cos(zy) - (7000 - cz) * sin(zy));
                        l4 = cz + (int) ((skyline - 700 - j4 * 70 - cy) * sin(zy) + (7000 - cz) * cos(zy));
                    }
                } else
                {
                    j5 = -skyline + 700 + j4 * 70 + h;
                    if (zy != 0 && j4 != 19)
                    {
                        j5 = cy + (int) ((-skyline + 700 + j4 * 70 + h - cy) * cos(zy) - (7000 - cz) * sin(zy));
                        l4 = cz + (int) ((-skyline + 700 + j4 * 70 + h - cy) * sin(zy) + (7000 - cz) * cos(zy));
                    }
                }

                ai[0] = iw - cx;
                if (j4 != 19)
                {
                    ai1[0] = ys(j5, l4);
                    if (ai1[0] > h + cx)
                    {
                        ai1[0] = h + cx;
                    }
                    if (ai1[0] < ih - cx)
                    {
                        ai1[0] = ih - cx;
                    }
                } else
                {
                    if (loops % 2 == 0)
                        ai1[0] = ih - cx;
                    else
                        ai1[0] = h + cx;
                }
                ai[1] = iw - cx;
                ai1[1] = j3;
                ai[2] = w + cx;
                ai1[2] = j3;
                ai[3] = w + cx;
                ai1[3] = ai1[0];
                j3 = ai1[0];
                i2 = (int) (i2 * 0.99099999999999999D);
                k2 = (int) (k2 * 0.99099999999999999D);
                i3 = (int) (i3 * 0.998D);
                rot(ai, ai1, cx, cy, xy, 4);
                graphics2d.setColor(new Color(i2, k2, i3));
                graphics2d.fillPolygon(ai, ai1, 4);
            }
        }
        zy += 180 * loops;
        zy++;
        xy++;
    }

    public float random() 
    {
        if (cntrn == 0) {
            int i = 0;
            do {
                rand[i] = (int) (10D * Math.random());
                if (Math.random() > Math.random())
                    diup[i] = false;
                else
                    diup[i] = true;
            } while (++i < 3);
            cntrn = 20;
        } else {
            cntrn--;
        }
        int j = 0;
        do
            if (diup[j]) {
                rand[j]++;
                if (rand[j] == 10)
                    rand[j] = 0;
            } else {
                rand[j]--;
                if (rand[j] == -1)
                    rand[j] = 9;
            }
        while (++j < 3);
        trn++;
        if (trn == 3)
            trn = 0;
        return rand[trn] / 10F;
    }

    public Medium() 
    {
            focus_point = 400;
            ground = 250;
            skyline = -300;
            fogd = 7;
            loadnew = false;
            lightson = false;
            darksky = false;
            lightn = -1;
            lilo = 217;
            lton = false;
            noelec = 0;
            trk = 0;
            crs = false;
            cx = 400;
            cy = 225;
            cz = 50;
            xz = 0;
            zy = 0;
            x = 0;
            y = -1000;
            z = 0;
            iw = 0;
            ih = 0;
            w = 800;
            h = 450;
            nsp = 0;
            spx = new int[7];
            spz = new int[7];
            sprad = new int[7];
            adv = 500;
            tcos = new float[360];
            tsin = new float[360];
            lastmaf = 0;
            checkpoint = -1;
            lastcheck = false;
            elecr = 0.0F;
            cpflik = false;
            nochekflk = false;
            cntrn = 0;
            trn = 0;
            hit = 45000;
            ogpx = null;
            ogpz = null;
            pvr = null;
            cgpx = null;
            cgpz = null;
            pmx = null;
            pcv = null;
            sgpx = 0;
            sgpz = 0;
            nrw = 0;
            ncl = 0;
            noc = 0;
            clx = null;
            clz = null;
            cmx = null;
            clax = null;
            clay = null;
            claz = null;
            clc = null;
            nmt = 0;
            mrd = null;
            nmv = null;
            mtx = null;
            mty = null;
            mtz = null;
            mtc = null;
            nst = 0;
            stx = null;
            stz = null;
            stc = null;
            bst = null;
            twn = null;
            resdown = 0;
            for (int i = 0; i < 360; i++)
            {
                tcos[i] = (float) Math.cos(i * 0.017453292519943295D);
            }
            for (int j = 0; j < 360; j++)
            {
                tsin[j] = (float) Math.sin(j * 0.017453292519943295D);
            }
            xy = 0;
    }

    public void rot(int ai[], int ai1[], int i, int j, int k, int l)
    {
        if(k != 0)
        {
            for(int i1 = 0; i1 < l; i1++)
            {
                int j1 = ai[i1];
                int k1 = ai1[i1];
                ai[i1] = i + (int)((float)(j1 - i) * cos(k) - (float)(k1 - j) * sin(k));
                ai1[i1] = j + (int)((float)(j1 - i) * sin(k) + (float)(k1 - j) * cos(k));
            }

        }
    }
}

共 (1) 个答案

  1. # 1 楼答案

    旋转和其他矩阵变换实际上很难正确进行。您看到的伪影可能是由于旋转代码中的逻辑错误或浮点精度错误造成的(您是否尝试过使用double而不是floats?)

    但好消息是你实际上不需要重新实现这个轮子。Java提供的^{}类正是为了这个目的。从本质上讲,您可以变换图形对象的状态,而不是正在绘制的元素本身。这是Java tutorial,还有很多related questions