#### Almost fixed: rotating a 2D shape.

Okay, so I've discovered the problem with rotating my shape around the centre point of it, so the code is still not yet perfect, but this is at least it's working to be a good enough starting point.

The comments should explain everything well enough I hope. I also added a scrolly text on the showStatus thingy in a true old-skool stylee. Here's the code:
Java Code:
```import java.awt.*;
import javax.swing.*;
import java.awt.Graphics;
import java.lang.Math;
/**
* This will draw a five-point star in an Applet and then
* bounce it around the canvas whilst rotating it ~1° clockwise.
* The alogrithmn is still imperfect, so there's some work to
* do but it's about >75% accurate.
*
* @author Shaun B
* @version 1.0.0a
* @todo    Perfect the maths so that it is >99% accurate when
*          rotating more complex shapes. Find the size in pixels
*          of the rotated shape against the original.
*/
public class starAnimation extends JApplet implements Runnable
{
// This array will draw a simple star:
private static final int STAR[] =
{
/** co-ordinates in array read as
* x0, y0 to x1, y1. -1 terminates */
0, 28, 30, 28,
39,  0, 50, 28,
79, 28, 55, 46,
64, 73, 40, 57,
15, 73, 23, 45,
-1, -1
};
// This is a rhombus:
private static int square[] =
{
0,  0, 80,  0,
80, 80,  0, 80,
-1, -1
};
// Here is our buffer for the shape:
private static int buffer[] =
{
-1, -1, -1, -1,
-1, -1, -1, -1,
-1, -1, -1, -1,
-1, -1, -1, -1,
-1, -1, -1, -1,
-1, -1, -1, -1,
-1, -1, -1, -1,
-1, -1, -1, -1,
-1, -1, -1, -1
};
// Here's a scrolly messahe:
private static String scrolly= " Nah nah na na nahh! :-P  Donkeysoft MMXII ";
private static String charBuffer = "";
// This will be used to rotate the shape, theta is
// converted to radians and therefore degrees
// can be within a more human range between zero
// and 360. The PI representation is accurate according
// to the Sinclair ZX81 :-)
private static double theta = (double)(1*3.1415927)/180;
private static double degrees = (double)0;
// Identity matrix and rotation matrix not yet
// implemented
/**private static int identity[][]=
{
{ 1, 0, 0, 0 },
{ 0, 1, 0, 0 },
{ 0, 0, 1, 0 }
{ 0, 0, 0, 1 }
};
private static double matrixRotate[][] =
{
{ Math.cos(0.10),   Math.sin(0.10),    0.00,   0.00 },
{ Math.sin(0.10),   Math.cos(0.10),     0.00,   0.00 },
{ 0.00,             0.00,               0.10,   0.00 },
{ 0.00,             0.00,               0.00,   0.10 }
};*/
// Starting position of star:
private int xAxis = 0;
private int yAxis = 0;
// Sets the height and width of the image:
private int widthOfStar = 80;
private int heightOfStar = 73;
private int widthOfSquare = 80;
private int heightOfSquare = 80;
// Sets the direction of the animation
// positive to move right/down and negative
// to move left/up:
private int xDirection = 1;
private int yDirection = 1;
// This will be used to get the width and height of the Applet
private int width=0;
private int height=0;
// This will be used to index through the array above:
private int index=0;
private Image backBuffer = null;
private Graphics backg = null;
/**
* Called by the browser or applet viewer to inform this JApplet that it
* has been loaded into the system. It is always called before the first
* time that the start method is called.
*/
@Override
public void init()
{
// This is a workaround for a security conflict with some browsers
// including some versions of Netscape & Internet Explorer which do
// not allow access to the AWT system event queue which JApplets do
// on startup to check access. May not be necessary with your browser.
JRootPane rootPane = this.getRootPane();
rootPane.putClientProperty("defeatSystemEventQueueCheck", Boolean.TRUE);
// Provide any initialisation necessary for your JApplet
// Gets the current width and height and creates a back buffer
// to that height:
this.width = getSize().width;
this.height = getSize().height;
this.backBuffer = createImage(width, height);
// Creates instance of the back buffer:
this.backg = backBuffer.getGraphics();
// Sets default behaviour as focusable:
this.setFocusable(true);
this.setVisible(true);
}
public void animate(int x, int y, int img[])
{
boolean xAndY = (x>=0) && (y>=0);
if(!xAndY)
{
showStatus("Problem with Animate");
}
rotate(x, y, img);
}
public void scrollText()
{
int stringLength = this.scrolly.length();
this.charBuffer=""+this.scrolly.charAt(0);
String stringBuffer = ""+
this.scrolly.substring(1, stringLength)+charBuffer;
this.scrolly = stringBuffer;
}
public void rotate(int x, int y,int [] img)
{
do
{
this.buffer[index]=img[index];
this.index++;
}while(img[index]>=0);
this.buffer[index+0]=-1;
this.buffer[index+1]=-1;
this.index=0;
this.heightOfStar = heightOfObject(heightOfStar, img);
this.widthOfStar = widthOfObject(widthOfStar, img);
// Divides width and height in half
int px=widthOfStar>>>1;
int py=heightOfStar>>>1;
// Sets up variables for the maths:
double x2=0.00;
double y2=0.00;
double x1=0.00;
double y1=0.00;
// Degrees to turn:
if(this.degrees>360)
{
this.degrees = (double)0;
}
this.degrees += (double)1;
this.theta = (double)(degrees*3.1415)/180;
while(this.buffer[index]>=0)
{
x1 = buffer[index+0];
y1 = buffer[index+1];
x2 = (double)px+(px-x1)*Math.cos(theta)-(py-y1)*Math.sin(theta);
y2 = (double)py+(px-x1)*Math.sin(theta)+(py-y1)*Math.cos(theta);
buffer[index+0]=(int)x2*1;
buffer[index+1]=(int)y2*1;
index += 2;
}
this.index = 0;
// Calls drawImage method:
this.drawImage(x, y, buffer);
}
public void drawImage(int x, int y, int [] img)
{
do
{
if(this.buffer[index]!=img[index])
{
System.err.println("Image not recognised");
}
this.index++;
}while(img[index]>=0);
this.index = 0;
int x0 = 0;
int y0 = 0;
int x1 = 0;
int y1 = 0;
// Sets the default foreground colour:
backg.setColor(Color.black);
// This will step through the array points to draw
// the star object. There is probably also a fillPolygon
// or drawPolygon method that could also be used:
while(this.buffer[index]>=0)
{
x0 = x+(this.buffer[index+0]);
y0 = y+(this.buffer[index+1]);
if (this.buffer[index+2]!=-1 && this.buffer[index+3]!=-1)
{
x1 = x+(this.buffer[index+2]);
y1 = y+(this.buffer[index+3]);
}
else
{
// Back to the start:
x1 = x+(this.buffer[0]);
y1 = y+(this.buffer[1]);
}
this.backg.drawLine( x0, y0, x1, y1 );
this.index += 2;
}
// Resets index to zero, incase the JApplet is reloaded or something:
this.index = 0;
}
public void clearBackBuffer()
{
// This will clear the canvas so that there is no trail left by the star
// by setting the default background colour and then filling it to the
// width and height of the canvas:
this.backg.setColor(Color.white);
this.backg.fillRect(0, 0, this.width, this.height);
}
/**
* Called by the browser or applet viewer to inform this JApplet that it
* should start its execution. It is called after the init method and
* each time the JApplet is revisited in a Web page.
*/
@Override
public void start()
{
if(this.runner == null)
{
this.runner.start();
}
// Call to parent (not needed):
// super.start();
}
/**
* Called by the browser or applet viewer to inform this JApplet that
* it should stop its execution. It is called when the Web page that
* contains this JApplet has been replaced by another page, and also
* just before the JApplet is to be destroyed.
*/
@Override
public void stop()
{
// Call to parent:
super.stop();
}
public int heightOfObject(int currentHeight, int [] obj)
{
this.index = 1;
while(obj[index]!=-1)
{
if(obj[index]>currentHeight)
{
currentHeight=obj[index];
}
this.index +=2;
}
this.index = 0;
return currentHeight;
}
public int widthOfObject(int currentWidth, int [] obj)
{
while(obj[index]!=-1)
{
if(obj[index]>currentWidth)
{
currentWidth=obj[index];
}
this.index +=2;
}
this.index = 0;
return currentWidth;
}
@Override
public void run()
{
// Checks if this thread has been set to runnable in the start method:
{
// Calls our method to draw the star:
animate(xAxis, yAxis, STAR);
try
{
// This is the time that it will pause in milliseconds
// 1000 = 1 second:
}
catch (InterruptedException e)
{
}
repaint();
// This will move the x and y co-ordinates of our object:
this.xAxis += this.xDirection;
this.yAxis += this.yDirection;
// This will check the boundries of the current applet canvas:
if(xAxis >= (width-widthOfStar))
{
this.xDirection =-1;
}
if(xAxis <= 0)
{
this.xDirection = 1;
}
if(yAxis >= (height-heightOfStar))
{
this.yDirection =-1;
}
if(yAxis <= 0)
{
this.yDirection = 1;
}
// Clears the canvas, so there is no 'trail'
// left by the moving star:
clearBackBuffer();
{
}
{
scrollText();
}
showStatus(scrolly);
}
}
// Main paint method (called on repaint(); I think):
@Override
public void paint(Graphics g)
{
// Calls to the update method:
update(g);
}
public void update(Graphics g)
{
// Gets the backBuffer and draws it to the canvas:
g.drawImage(backBuffer,0,0,this);
// the sync toolkit is used for animations as it stops flicker:
getToolkit().sync();
}
/**
* Called by the browser or applet viewer to inform this JApplet that it
* is being reclaimed and that it should destroy any resources that it
* has allocated. The stop method will always be called before destroy.
*/
@Override
public void destroy()
{
// Calls the garbage collector before calling parent:
this.runner = null;
super.destroy();
}
}```

Regards,

Shaun.