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

时间:2015-06-29 04:30:18

标签: java polygon graphics2d

我正在尝试为游戏扩展实现滚动角度,并且为了模拟它,我最好的方法是围绕屏幕中心旋转矩形。

问题是当我用简单的旋转功能旋转矩形时,会出现黑色条纹(注意我使用的是BufferStrategy)。

截图

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],第二个矩形的坐标为[100,100,200,200],依此类推。

我不想使用Graphics2D.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 个答案:

答案 0 :(得分:0)

旋转和其他矩阵变换实际上很难做到。您看到的工件很可能是由于旋转代码中的逻辑错误或浮点精度错误(您是否尝试使用double而不是float?)。< / p>

但好消息是,你实际上并不需要重新实现这个轮子。 Java完全为此目的提供AffineTransform类。基本上,您可以转换图形对象的状态,而不是您自己绘制的元素。这里是Java tutorial,还有很多related questions