Advertisement
Shaun_B

WIP: Bouncing and rotating a star around a canvas

Nov 4th, 2012
483
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 12.14 KB | None | 0 0
  1. import java.awt.*;
  2. import javax.swing.*;
  3. import java.awt.Graphics;
  4. import java.lang.Math;
  5. /**
  6.  * This will draw a five-point star in an Applet and then
  7.  * bounce it around the canvas whilst rotating it ~1° clockwise.
  8.  * The alogrithmn is still imperfect, so there's some work to
  9.  * do but it's about >75% accurate.
  10.  *
  11.  * @author Shaun B
  12.  * @version 1.0.0a
  13.  * @todo    Perfect the maths so that it is >99% accurate when
  14.  *          rotating more complex shapes. Find the size in pixels
  15.  *          of the rotated shape against the original.
  16.  */
  17. public class starAnimation extends JApplet implements Runnable
  18. {
  19.     // This array will draw a simple star:
  20.     private static final int STAR[] =
  21.     {
  22.         /** co-ordinates in array read as
  23.          * x0, y0 to x1, y1. -1 terminates */
  24.          0, 28, 30, 28,
  25.         39,  0, 50, 28,
  26.         79, 28, 55, 46,
  27.         64, 73, 40, 57,
  28.         15, 73, 23, 45,
  29.         -1, -1
  30.     };
  31.     // This is a rhombus:
  32.     private static int square[] =
  33.     {
  34.          0,  0, 80,  0,
  35.         80, 80,  0, 80,
  36.         -1, -1
  37.     };
  38.     // Here is our buffer for the shape:
  39.     private static int buffer[] =
  40.     {
  41.         -1, -1, -1, -1,
  42.         -1, -1, -1, -1,
  43.         -1, -1, -1, -1,
  44.         -1, -1, -1, -1,
  45.         -1, -1, -1, -1,
  46.         -1, -1, -1, -1,
  47.         -1, -1, -1, -1,
  48.         -1, -1, -1, -1,
  49.         -1, -1, -1, -1
  50.     };
  51.     // Here's a scrolly messahe:
  52.     private static String scrolly= " Nah nah na na nahh! :-P  Donkeysoft MMXII ";
  53.     private static String charBuffer = "";
  54.     private byte updateScrolly = 0;
  55.     // This will be used to rotate the shape, theta is
  56.     // converted to radians and therefore degrees
  57.     // can be within a more human range between zero
  58.     // and 360. The PI representation is accurate according
  59.     // to the Sinclair ZX81 :-)
  60.     private static double theta = (double)(1*3.1415927)/180;
  61.     private static double degrees = (double)0;
  62.     // Identity matrix and rotation matrix not yet
  63.     // implemented
  64.     /**private static int identity[][]=
  65.     {
  66.         { 1, 0, 0, 0 },
  67.         { 0, 1, 0, 0 },
  68.         { 0, 0, 1, 0 }
  69.         { 0, 0, 0, 1 }
  70.     };
  71.     private static double matrixRotate[][] =
  72.     {
  73.         { Math.cos(0.10),   Math.sin(0.10),    0.00,   0.00 },
  74.         { Math.sin(0.10),   Math.cos(0.10),     0.00,   0.00 },
  75.         { 0.00,             0.00,               0.10,   0.00 },
  76.         { 0.00,             0.00,               0.00,   0.10 }
  77.     };*/
  78.     // Starting position of star:
  79.     private int xAxis = 0;
  80.     private int yAxis = 0;
  81.     // Sets the height and width of the image:
  82.     private int widthOfStar = 80;
  83.     private int heightOfStar = 73;
  84.     private int widthOfSquare = 80;
  85.     private int heightOfSquare = 80;
  86.     // Sets the direction of the animation
  87.     // positive to move right/down and negative
  88.     // to move left/up:
  89.     private int xDirection = 1;
  90.     private int yDirection = 1;
  91.     // This will be used to get the width and height of the Applet
  92.     private int width=0;
  93.     private int height=0;
  94.     // This will be used to index through the array above:
  95.     private int index=0;
  96.     // Read up about back buffering, as it's important ;-)
  97.     private Image backBuffer = null;
  98.     private Graphics backg = null;
  99.     // This will be our thread, you need to know about threads too:
  100.     private Thread runner = null;
  101.      /**
  102.      * Called by the browser or applet viewer to inform this JApplet that it
  103.      * has been loaded into the system. It is always called before the first
  104.      * time that the start method is called.
  105.      */
  106.     @Override
  107.     public void init()
  108.     {
  109.         // This is a workaround for a security conflict with some browsers
  110.         // including some versions of Netscape & Internet Explorer which do
  111.         // not allow access to the AWT system event queue which JApplets do
  112.         // on startup to check access. May not be necessary with your browser.
  113.         JRootPane rootPane = this.getRootPane();    
  114.         rootPane.putClientProperty("defeatSystemEventQueueCheck", Boolean.TRUE);
  115.         // Provide any initialisation necessary for your JApplet
  116.         // Gets the current width and height and creates a back buffer
  117.         // to that height:
  118.         this.width = getSize().width;
  119.         this.height = getSize().height;
  120.         this.backBuffer = createImage(width, height);
  121.         // Creates instance of the back buffer:
  122.         this.backg = backBuffer.getGraphics();
  123.         // Sets default behaviour as focusable:
  124.         this.setFocusable(true);
  125.         this.setVisible(true);
  126.     }
  127.     public void animate(int x, int y, int img[])
  128.     {
  129.         boolean xAndY = (x>=0) && (y>=0);
  130.         if(!xAndY)
  131.         {
  132.             showStatus("Problem with Animate");
  133.         }
  134.         rotate(x, y, img);
  135.     }
  136.     public void scrollText()
  137.     {
  138.        int stringLength = this.scrolly.length();
  139.        this.charBuffer=""+this.scrolly.charAt(0);
  140.        String stringBuffer = ""+
  141.             this.scrolly.substring(1, stringLength)+charBuffer;
  142.        this.scrolly = stringBuffer;
  143.     }
  144.     public void rotate(int x, int y,int [] img)
  145.     {
  146.         do
  147.         {
  148.             this.buffer[index]=img[index];
  149.             this.index++;
  150.         }while(img[index]>=0);
  151.         this.buffer[index+0]=-1;
  152.         this.buffer[index+1]=-1;
  153.         this.index=0;
  154.         this.heightOfStar = heightOfObject(heightOfStar, img);
  155.         this.widthOfStar = widthOfObject(widthOfStar, img);
  156.         // Divides width and height in half
  157.         int px=widthOfStar>>>1;
  158.         int py=heightOfStar>>>1;
  159.         // Sets up variables for the maths:
  160.         double x2=0.00;
  161.         double y2=0.00;
  162.         double x1=0.00;
  163.         double y1=0.00;
  164.         // Degrees to turn:
  165.         if(this.degrees>360)
  166.         {
  167.             this.degrees = (double)0;
  168.         }
  169.         this.degrees += (double)1;
  170.         this.theta = (double)(degrees*3.1415)/180;
  171.         while(this.buffer[index]>=0)
  172.         {
  173.             x1 = buffer[index+0];
  174.             y1 = buffer[index+1];
  175.             x2 = (double)px+(px-x1)*Math.cos(theta)-(py-y1)*Math.sin(theta);
  176.             y2 = (double)py+(px-x1)*Math.sin(theta)+(py-y1)*Math.cos(theta);
  177.             buffer[index+0]=(int)x2*1;
  178.             buffer[index+1]=(int)y2*1;
  179.             index += 2;
  180.         }
  181.         this.index = 0;
  182.         // Calls drawImage method:
  183.         this.drawImage(x, y, buffer);
  184.     }
  185.     public void drawImage(int x, int y, int [] img)
  186.     {
  187.         do
  188.         {
  189.             if(this.buffer[index]!=img[index])
  190.             {
  191.                 System.err.println("Image not recognised");
  192.             }
  193.             this.index++;
  194.         }while(img[index]>=0);
  195.         this.index = 0;
  196.         int x0 = 0;
  197.         int y0 = 0;
  198.         int x1 = 0;
  199.         int y1 = 0;
  200.         // Sets the default foreground colour:
  201.         backg.setColor(Color.black);
  202.         // This will step through the array points to draw
  203.         // the star object. There is probably also a fillPolygon
  204.         // or drawPolygon method that could also be used:
  205.         while(this.buffer[index]>=0)
  206.         {
  207.             x0 = x+(this.buffer[index+0]);
  208.             y0 = y+(this.buffer[index+1]);
  209.             if (this.buffer[index+2]!=-1 && this.buffer[index+3]!=-1)
  210.             {
  211.                 x1 = x+(this.buffer[index+2]);
  212.                 y1 = y+(this.buffer[index+3]);
  213.             }
  214.             else
  215.             {
  216.                 // Back to the start:
  217.                 x1 = x+(this.buffer[0]);
  218.                 y1 = y+(this.buffer[1]);
  219.             }
  220.             this.backg.drawLine( x0, y0, x1, y1 );
  221.             this.index += 2;
  222.         }
  223.         // Resets index to zero, incase the JApplet is reloaded or something:
  224.         this.index = 0;
  225.     }
  226.     public void clearBackBuffer()
  227.     {
  228.         // This will clear the canvas so that there is no trail left by the star
  229.         // by setting the default background colour and then filling it to the
  230.         // width and height of the canvas:
  231.         this.backg.setColor(Color.white);
  232.         this.backg.fillRect(0, 0, this.width, this.height);
  233.     }
  234.     /**
  235.      * Called by the browser or applet viewer to inform this JApplet that it
  236.      * should start its execution. It is called after the init method and
  237.      * each time the JApplet is revisited in a Web page.
  238.      */
  239.     @Override
  240.     public void start()
  241.     {
  242.        // Sets up the thread:
  243.        if(this.runner == null)
  244.        {
  245.            this.runner = new Thread(this);
  246.            this.runner.start();
  247.        }
  248.        // Call to parent (not needed):
  249.        // super.start();
  250.     }
  251.     /**
  252.      * Called by the browser or applet viewer to inform this JApplet that
  253.      * it should stop its execution. It is called when the Web page that
  254.      * contains this JApplet has been replaced by another page, and also
  255.      * just before the JApplet is to be destroyed.
  256.      */
  257.     @Override
  258.     public void stop()
  259.     {
  260.         // Call to parent:
  261.         super.stop();
  262.     }
  263.     public int heightOfObject(int currentHeight, int [] obj)
  264.     {
  265.         this.index = 1;
  266.         while(obj[index]!=-1)
  267.         {
  268.             if(obj[index]>currentHeight)
  269.             {
  270.                 currentHeight=obj[index];
  271.             }
  272.             this.index +=2;
  273.         }
  274.         this.index = 0;
  275.         return currentHeight;
  276.     }
  277.     public int widthOfObject(int currentWidth, int [] obj)
  278.     {
  279.         while(obj[index]!=-1)
  280.         {
  281.             if(obj[index]>currentWidth)
  282.             {
  283.                 currentWidth=obj[index];
  284.             }
  285.             this.index +=2;
  286.         }
  287.         this.index = 0;
  288.         return currentWidth;
  289.     }
  290.     @Override
  291.     public void run()
  292.     {
  293.         // Checks if this thread has been set to runnable in the start method:
  294.         Thread thisThread = Thread.currentThread();
  295.         while (runner == thisThread)
  296.         {
  297.             // Calls our method to draw the star:
  298.             animate(xAxis, yAxis, STAR);
  299.             try
  300.             {
  301.                 // This is the time that it will pause in milliseconds
  302.                 // 1000 = 1 second:
  303.                 Thread.sleep(33);
  304.             }
  305.             catch (InterruptedException e)
  306.             {
  307.             }
  308.             repaint();
  309.             // This will move the x and y co-ordinates of our object:
  310.             this.xAxis += this.xDirection;
  311.             this.yAxis += this.yDirection;
  312.             // This will check the boundries of the current applet canvas:
  313.             if(xAxis >= (width-widthOfStar))
  314.             {
  315.                 this.xDirection =-1;
  316.             }
  317.             if(xAxis <= 0)
  318.             {
  319.                 this.xDirection = 1;
  320.             }
  321.             if(yAxis >= (height-heightOfStar))
  322.             {
  323.                 this.yDirection =-1;
  324.             }
  325.             if(yAxis <= 0)
  326.             {
  327.                 this.yDirection = 1;
  328.             }
  329.             // Clears the canvas, so there is no 'trail'
  330.             // left by the moving star:
  331.             clearBackBuffer();
  332.             this.updateScrolly++;
  333.             if(this.updateScrolly>128)
  334.             {
  335.                 this.updateScrolly = 0;
  336.             }
  337.             if(this.updateScrolly%4 == 0)
  338.             {
  339.                 scrollText();
  340.             }
  341.             showStatus(scrolly);
  342.         }
  343.     }
  344.     // Main paint method (called on repaint(); I think):
  345.     @Override
  346.     public void paint(Graphics g)
  347.     {
  348.         // Calls to the update method:
  349.         update(g);
  350.     }
  351.     public void update(Graphics g)
  352.     {
  353.         // Gets the backBuffer and draws it to the canvas:
  354.         g.drawImage(backBuffer,0,0,this);
  355.         // the sync toolkit is used for animations as it stops flicker:
  356.         getToolkit().sync();
  357.     }
  358.     /**
  359.      * Called by the browser or applet viewer to inform this JApplet that it
  360.      * is being reclaimed and that it should destroy any resources that it
  361.      * has allocated. The stop method will always be called before destroy.
  362.      */
  363.     @Override
  364.     public void destroy()
  365.     {
  366.         // Calls the garbage collector before calling parent:
  367.         this.runner = null;
  368.         super.destroy();
  369.     }
  370. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement