Related
I've got 8 ovals all set to the same colour. After a second I want the first oval to change colours and then after another second i want the first oval to go back to its original colour and then change the second ovals colour. I've drawn the circles and I've tried implementing a thread but i think it's not executing...
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Circle extends JPanel implements Runnable
{
Graphics g;
Thread t = new Thread();
int[][] fillCircles = new int[8][4];
#Override
public void paintComponent(Graphics g)
{
this.g = g;
super.paintComponent(this.g);
this.g.setColor(new java.awt.Color(237, 54, 26));
this.g.drawOval(300, 50, 100, 100);
this.g.drawOval(450, 125, 100, 100);
this.g.drawOval(500, 250, 100, 100);
this.g.drawOval(425, 375, 100, 100);
this.g.drawOval(300, 400, 100, 100);
this.g.drawOval(175, 350, 100, 100);
this.g.drawOval(125, 225, 100, 100);
this.g.drawOval(175, 100, 100, 100);
this.g.fillOval(300, 50, 100, 100);
this.g.fillOval(450, 125, 100, 100);
this.g.fillOval(500, 250, 100, 100);
this.g.fillOval(425, 375, 100, 100);
this.g.fillOval(300, 400, 100, 100);
this.g.fillOval(175, 350, 100, 100);
this.g.fillOval(125, 225, 100, 100);
this.g.fillOval(175, 100, 100, 100);
fillCircles[0][0] = 300;
fillCircles[0][1] = 50;
fillCircles[0][2] = 100;
fillCircles[0][3] = 100;
fillCircles[1][0] = 450;
fillCircles[1][1] = 125;
fillCircles[1][2] = 100;
fillCircles[1][3] = 100;
fillCircles[2][0] = 500;
fillCircles[2][1] = 250;
fillCircles[2][2] = 100;
fillCircles[2][3] = 100;
fillCircles[3][0] = 425;
fillCircles[3][1] = 375;
fillCircles[3][2] = 100;
fillCircles[3][3] = 100;
fillCircles[4][0] = 300;
fillCircles[4][1] = 400;
fillCircles[4][2] = 100;
fillCircles[4][3] = 100;
fillCircles[5][0] = 175;
fillCircles[5][1] = 350;
fillCircles[5][2] = 100;
fillCircles[5][3] = 100;
fillCircles[6][0] = 125;
fillCircles[6][1] = 225;
fillCircles[6][2] = 100;
fillCircles[6][3] = 100;
fillCircles[7][0] = 175;
fillCircles[7][1] = 100;
fillCircles[7][2] = 100;
fillCircles[7][3] = 100;
}
Circle () {
t.start();
}
public void run () {
int circle = 0;
try {
for (;;) {
Thread.sleep(1000);
if (circle > 0) {
this.g.setColor(new java.awt.Color(237, 54, 26));
circle--;
this.g.fillOval(fillCircles[circle][0], fillCircles[circle][1], fillCircles[circle][2], fillCircles[circle][2]);
circle++;
}
this.g.setColor(Color.red);
this.g.fillOval(fillCircles[circle][0], fillCircles[circle][1], fillCircles[circle][2], fillCircles[circle][2]);
circle++;
if (circle == 8) {
circle = 0;
}
}
} catch (InterruptedException e) {
System.out.println ("Thread Interrupted");
}
}
public static void main(String[] args) {
Circle c;
JFrame application = new JFrame();
application.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
application.add(c=new Circle());
application.setSize(1200, 900);
application.setVisible(true);
}
}
You're just instantiating a Thread without giving it a Runnable, so it's not running what you're intending.
Thread t = new Thread();
should be
Thread t = new Thread(this);
this because the Circle is Runnable and the run() method is in it.
Regarding color changing, I would give you an idea.
When drawing the circles, check the current circle number/index against another variable which changes every second colorChangeIndex
if(circleIndex == colorChangeIndex){
// another color
else
//the default color
colorChangeIndex++; (modulo number of cricles to reset it)
The basic structure of your code is wrong. Painting should only be done in the paintComponent() method. You should never reference the Graphics object in your thread.
So, instead what you might want to do is keep an ArrayList of "circle" objects. This custom object will contain the circle to be painted and its color. Then in the paintComponent() method you just iterate through the ArrayList and paint all the circles in the ArrayList. Check out the DrawOnComponent example found in Custom Painting Approches.
After a second I want the first oval to change colours and then after another second i want the first oval to go back to its original colour and then change the second ovals colour.
So now you need to use a Swing Timer to animate the painting. When the Timer fires you reset the Color of the appropriate circle and then just repaint the panel.
I have a graphic which consists of a horizontal line of circles of different sizes at regular intervals. Here is the picture:
I am trying to recreate this graphic using recursion as opposed to the if statements used in my code but after trying, am unsure about how to do this. Would love some help, here is my code:
package weekFour;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import javax.swing.*;
#SuppressWarnings("serial")
public class Circle extends JPanel {
private int circX = 10;
private static int windowW = 1700;
private static int windowH = 1000;
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); //smoothes out edges
Color c5 = new Color(50, 50, 50);
Color c4 = new Color(100, 100, 100);
Color c3 = new Color(150, 150, 150);
Color c2 = new Color(200, 200, 200);
Color c1= new Color(250, 250, 250);
for (int i = 0; i < 1; i++) {
g2.setColor(c1);
g2.fillOval(522 + 75*i, 138, 666, 666);
g2.setColor(c1);
g2.drawOval(522 + 75*i, 138, 666, 666);
}
for (int i = 0; i < 3; i++) {
g2.setColor(c2);
g2.fillOval(244 + 522*i, 365, 180, 180);
g2.setColor(c2);
g2.drawOval(244 + 522*i, 365, 180, 180);
}
for (int i = 0; i < 10; i++) {
g2.setColor(c3);
g2.fillOval(130 + 174*i, 428, 60, 60);
g2.setColor(c3);
g2.drawOval(130 + 174*i, 428, 60, 60);
}
for (int i = 0; i < 25; i++) {
g2.setColor(c4);
g2.fillOval(60 + 87*i, 444, 25, 25);
g2.setColor(c4);
g2.drawOval(60 + 87*i, 444, 25, 25);
}
for (int i = 0; i < 120; i++) {
g2.setColor(c5);
g2.fillOval(circX + 29*i, 450, 12, 12);
g2.setColor(c5);
g2.drawOval(circX + 29*i, 450, 12, 12);
}
}
private static void createAndShowGui() {
JFrame frame = new JFrame("MyTaskToo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new Circle());
frame.setSize(windowW, windowH);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
Thanks for your time.
This is how I went about this problem, although we had to do it with green circles as opposed to grey circles but it's not that different.
N.B: Sorry for the appealing comments for sometimes trivial things but we get marks for commenting and it is better to be safe than sorry. Maybe they change you some insight into the thought process.
Here is the main method that starts the programme and sets out the window information.
public class Q2Main {
public static void main(String[] args) {
// here we are just setting out the window end putting the circles drawin in Q2Circles into this window.
JFrame window = new JFrame();
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setSize(1000, 500);
window.getContentPane().add(new Q2Circles(5));
window.setVisible(true);
}}
This is where the magic happens:
public class Q2Circles extends JPanel {
// this allows the user to specify how many loops of recursion they want the programme to complete before finishing
int recursionsToDo;
public Q2Circles(int recursionMax){
super();
recursionsToDo = recursionMax;
}
/*
this method is automatically called when we run the constructor as it inherits from the JFram superclass. here
we are setting out the size of the circle by getting the size of the window to make it proportional to the rest
of the screen and circles.
we then pass these values into the drawCircle method to draw the circle
*/
public void paintComponent(Graphics g){
Rectangle rectangle = this.getBounds();
int diameter = rectangle.width/3;
int centerPoint = rectangle.width/2;
drawCircle(g, 1, centerPoint, diameter);
}
/*
This method is where the magic of the programme really takes place. first of all we make sure we haven't completed
the necessary recursions. we the set the color by dividing it by the amount of times we have recursed, this will
have the affect of getting darker the more times the method recurses. we then sset the color. finaly we fill the
oval (draw the circle). because we want to move depending on the times it has recursed and size of the previous
we do it based on the size of the elements from the previous call to this method. Getting the right numbers
though was just alot of trial and error.
we then increment the recursion counter so that we know how many times we have recursed and that can then be
used at different points where needed. e.g for setting the color.
each recursive call used the dimension of the other recursive calls to make the whole picture. Although the
first recursive call creates the circles on the right of the screen. the second call draws the circle on the
left of the screen and the last one does the circles in the middle, they all use eachothers values to make it
complete. without one recursive step, more is missing than just what is created by that recursive call on its own.
in all honesty though, there is alot of duplication, like the large middlecircle.
*/
public void drawCircle(Graphics g, int amountOfRecursions, int center, int diameter){
if (amountOfRecursions <= recursionsToDo){
int recursionsCount = amountOfRecursions;
int greenColor = Math.round(225 / (amountOfRecursions));
g.setColor(new Color(0, greenColor, 0));
g.fillOval(center - (diameter/2), 200 - (diameter/2), diameter, diameter);
recursionsCount++;
drawCircle(g, recursionsCount, Math.round(center + diameter), diameter/3);
drawCircle(g, recursionsCount, Math.round(center - diameter), diameter/3);
drawCircle(g, recursionsCount, Math.round(center), diameter/3);
}
}}
I'm new to Java so thank you for your time and help!
Basically I want to get text to display over a graphic I have created. Basically I made a trophy and want it to display "#1" on it.
Can anyone please help me with how to do this? Thank you again
Below is the code I have written so far. You can see that the position for the "#1" is all set and done but it's appearing behind the graphic.
import javax.swing.JApplet;
import java.awt.*;
import java.net.*;
import javax.imageio.*;
import java.io.*;
import java.awt.Graphics2D;
public class BusinessCard extends JApplet
{
/**
* Paint method for applet.
*
* #param g the Graphics object for this applet
*/
public void paint(Graphics page)
{
//Variables used in rectangle
int x = 0;
int y = 0;
int width = 500;
int height = 300;
page.drawRect(x, y, width, height); //draws the rectangle using variables
//Displays name
Font f = new Font("Helvetica", Font.BOLD, 26);
page.setFont(f);
page.drawString ("anonymous", 300,100);
//Displays company
Font g = new Font("Helvetica", Font.PLAIN, 18);
page.setFont(g);
page.drawString ("blank", 320, 120);
//Displays email
Font h = new Font("Helvetica", Font.PLAIN, 15);
page.setFont(h);
page.drawString ("email", 315,140);
//int for the logo
final int MID = 350;
final int TOP = 168;
setBackground (Color.yellow); //Revisit. For some reason it only turns yellow after you resize the window
Font i = new Font("Helvetica", Font.BOLD, 16);
page.setFont(i);
page.drawString ("#1", MID+20, TOP+20);
page.setColor (Color.orange);
page.fillOval (MID, TOP, 60, 60); //bottom half of the trophy. the rounded part.
page.drawArc (MID-8, TOP+15, 25, 25, 100, 160); //left arc
page.drawArc (MID+43, TOP+15 , 25, 25, 280, 160); //right arc
page.fillRect (MID+1, TOP+1, 59, 25); //make the top of the trophy flat basically
page.fillRect (MID+22, TOP+60, 15, 25); //neck of the trophy
page.drawLine (MID+48, TOP+84, MID+10, TOP+84); //base of the trophy
}
I think you have to draw the trophy first and then write the text!
Whatever you draw appears on the top layer of the control.
First, do what sabre_raider said. You do want it before, but something else must be fixed too
You're drawing orange on orange. You draw the trophy, then set the background of your page to be yellow, then draw the "#1" in orange again. Change setBackground to page.setColor to draw in yellow (which appears to be what you want). setBackground sets the background of the applet, which im assuming is not what you want, but rather to draw the "#1" in yellow. If you did mean to set the background, make sure to do that in Applet's init method!! Not each time you repaint. (Along with that, in init, have setSize(500, 300) to properly size the window to the size of your message)
Also, I recomend splitting that up into different methods, as that will just make it more readable. Here's what your methods should look like in general:
/**
* Paint method for applet.
*
* #param g
* the Graphics object for this applet
*/
public void paint(Graphics page)
{
drawBorder( page );
drawText( page );
drawTrophy( page, 1 );
}
private void drawBorder(Graphics page) {
int x = 0;
int y = 0;
int width = 500;
int height = 300;
page.setColor( Color.black );
page.drawRect( x, y, width, height );
}
private void drawText(Graphics page) {
// Displays name
Font f = new Font( "Helvetica", Font.BOLD, 26 );
page.setFont( f );
page.drawString( "anonymous", 300, 100 );
// Displays company
Font g = new Font( "Helvetica", Font.PLAIN, 18 );
page.setFont( g );
page.drawString( "blank", 320, 120 );
// Displays email
Font h = new Font( "Helvetica", Font.PLAIN, 15 );
page.setFont( h );
page.drawString( "email", 315, 140 );
}
private void drawTrophy(Graphics page, int number) {
final int MID = 350;
final int TOP = 168;
page.setColor( Color.orange );
page.fillOval( MID, TOP, 60, 60 ); // bottom half of the trophy. the rounded part.
page.drawArc( MID - 8, TOP + 15, 25, 25, 100, 160 ); // left arc
page.drawArc( MID + 43, TOP + 15, 25, 25, 280, 160 ); // right arc
page.fillRect( MID + 1, TOP + 1, 59, 25 ); // make the top of the trophy flat basically
page.fillRect( MID + 22, TOP + 60, 15, 25 ); // neck of the trophy
page.drawLine( MID + 48, TOP + 84, MID + 10, TOP + 84 ); // base of the trophy
Font i = new Font( "Helvetica", Font.BOLD, 16 );
page.setColor( Color.yellow );
page.setFont( i );
page.drawString( "#" + number, MID + 20, TOP + 20 );
}
Firstly, I wouldn't paint directly onto a top level container. I'd use something like a JPanel to do my custom painting and then add that to the top level container.
Secondly, you should avoid overriding paint where possible. If you use a custom component as suggested in the first point, you should use paintComponent instead.
Thirdly, ALWAYS call super.paint (or super.paintComponent if you're using a custom component).
Fourthly, ever body else is right. You should be trying to draw you text AFTER the graphics...
This is the code I used:
public class BusinessCard extends JApplet {
/**
* Paint method for applet.
*
* #param g the Graphics object for this applet
*/
public void paint(Graphics page) {
super.paint(page);
//Variables used in rectangle
int x = 0;
int y = 0;
int width = 500;
int height = 300;
page.drawRect(x, y, width, height); //draws the rectangle using variables
//int for the logo
final int MID = 350;
final int TOP = 168;
page.setColor(Color.orange);
page.fillOval(MID, TOP, 60, 60); //bottom half of the trophy. the rounded part.
page.drawArc(MID - 8, TOP + 15, 25, 25, 100, 160); //left arc
page.drawArc(MID + 43, TOP + 15, 25, 25, 280, 160); //right arc
page.fillRect(MID + 1, TOP + 1, 59, 25); //make the top of the trophy flat basically
page.fillRect(MID + 22, TOP + 60, 15, 25); //neck of the trophy
page.drawLine(MID + 48, TOP + 84, MID + 10, TOP + 84); //base of the trophy
page.setColor(Color.yellow); //Revisit. For some reason it only turns yellow after you resize the window
Font font = UIManager.getFont("Label.font");
page.setFont(font.deriveFont(Font.BOLD, 16));
page.drawString("#1", MID + 20, TOP + 20);
//Displays name
page.setFont(font.deriveFont(Font.BOLD, 26));
page.drawString("anonymous", 300, 100);
//Displays company
page.setFont(font.deriveFont(Font.PLAIN, 18));
page.drawString("blank", 320, 120);
//Displays email
page.setFont(font.deriveFont(Font.PLAIN, 15));
page.drawString("email", 315, 140);
}
}
And it produced
Beware, that everybody may have the font you're trying to use installed (you code caused the applet to crash)
I'm trying to build a 2d game.
I have a background-image that static and an Image of the character. When i press a move-key (WASD) the Mainclass (were the keylistener is) calling a function in a class called Player The function is changing the location of the character (Image). And after this function is called i use repaint() to repaint the character on new position.
If i remove the background i can see the old images still left from the other positions. So this meens i have to repaint the player and the background for each step.
There might be a better solution for this? Worst case scenario: It's an onlinegame and there are many players moving around and each 100 milliseconds the repaint is called for update every players posisions. I have a feeling this will take out all the memory of the players computer or at least the game will not feel so good
Don't paint directly in the JFrame content pane. Instead, override paintComponent() in a JComponent. This AnimationTest draws into a JPanel, which is double buffered by default. The example also shows one approach to examining the time budget devoted to painting.
As far as I know, there is no other solution. Repainting every 100 ms generally isn't too memory intensive on most computers.
I think repaint is the only solution, I once created a 2d car simulation game and that's what i do, I also change the coordinates of all Car objects and then repaint the whole thing. I tried to simulate 2000 Car objects running at 100 ms repaint on all of them without trouble. hehe fun
(i used a jpanel inside the jframe) and use bufferedimage of java.awt.image
Instead you can try using a JLabel with Icons. Then all you do is invoke the setLocation(...) method of the label. The Swing RepaintManager will look after repainting the old location and the new location.
Here's an example to get you started. This example uses separate Timers for each image. In your game you would reset the location of all images at the same time when your single Timer fires.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class AnimationBackground extends JLabel implements ActionListener
{
int deltaX = 2;
int deltaY = 3;
int directionX = 1;
int directionY = 1;
public AnimationBackground(
int startX, int startY,
int deltaX, int deltaY,
int directionX, int directionY,
int delay)
{
this.deltaX = deltaX;
this.deltaY = deltaY;
this.directionX = directionX;
this.directionY = directionY;
setIcon( new ImageIcon("dukewavered.gif") );
setSize( getPreferredSize() );
setLocation(startX, startY);
new javax.swing.Timer(delay, this).start();
}
public void actionPerformed(ActionEvent e)
{
Container parent = getParent();
// Determine next X position
int nextX = getLocation().x + (deltaX * directionX);
if (nextX < 0)
{
nextX = 0;
directionX *= -1;
}
if ( nextX + getSize().width > parent.getSize().width)
{
nextX = parent.getSize().width - getSize().width;
directionX *= -1;
}
// Determine next Y position
int nextY = getLocation().y + (deltaY * directionY);
if (nextY < 0)
{
nextY = 0;
directionY *= -1;
}
if ( nextY + getSize().height > parent.getSize().height)
{
nextY = parent.getSize().height - getSize().height;
directionY *= -1;
}
// Move the label
setLocation(nextX, nextY);
}
public static void main(String[] args)
{
JPanel panel = new JPanel(null)
{
Image image = new ImageIcon("mong.jpg").getImage();
protected void paintComponent(Graphics g)
{
g.drawImage(image, 0, 0, getWidth(), getHeight(), null);
super.paintComponent(g);
}
};
panel.setOpaque(false);
// panel.add( new AnimationBackground(10, 10, 2, 3, 1, 1, 10) );
panel.add( new AnimationBackground(300, 100, 3, 2, -1, 1, 20) );
panel.add( new AnimationBackground(200, 200, 2, 3, 1, -1, 20) );
panel.add( new AnimationBackground(50, 50, 5, 5, -1, -1, 20) );
// panel.add( new AnimationBackground(0, 000, 5, 0, 1, 1, 20) );
panel.add( new AnimationBackground(0, 200, 5, 0, 1, 1, 80) );
JFrame frame = new JFrame();
frame.setContentPane(panel);
frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
frame.setSize(400, 400);
frame.setLocationRelativeTo( null );
frame.setVisible(true);
}
}
You will need to provide a background image and an image for the label where the code creates an ImageIcon.
There is efficient to redraw only part of your component. Read this tutorial.
Basically you have to call component.repaint(posX, posY, length, height) twice:
once at he old player image position (will repaint the background) and then at the new position.
(This solution was also proposed by G_H in the comments.)
I'm making a Pinball style applet and I ran into some problems before that have thankfully been remedied. However, I've hit another stumbling block.
To draw flippers for the pinball machine, I intended to draw an angled rounded rectangle which would allow me to possibly animate it later on so that you could see it moving up when I add threads to the applet. This is all done in the Table's paintComponent method. When I don't apply any rotation to check that it's all working ok, it draws the shape fine. But when I apply a rotation (whether through an Affine Transform object as in my code now or the Graphics2D.rotate method) the shape does not draw for some reason. I'm not sure why but I'm hoping that I've merely overlooked something. I have looked around online, but either I'm not putting in the right keywords or it is simply that I'm overlooking something.
The code for my Pinball and Table classes is below, please feel free to point out anything that you think could cause this strangeness. Note that I haven't given the right coordinates exactly yet as I can tweek it's position when it's drawn and I can see it, in case any of you run any similar code to try and debug it.
As a P.S. Would calling the ball's constructor on table be a better idea than doing it on the applet? Just wondering if what I've done with that is really inefficient.
import javax.swing.*; // useful for the drawing side, also going to be a JApplet
import java.awt.*;
import java.net.*;
public class Pinball extends JApplet
{
// variables go here
Table table;
Player player;
Ball ball;
Miosoft miosoft;
Miofresh miofresh;
Mioboost mioboost;
Miocare miocare;
Miowipe miowipe;
// further initialisation of the GUI
public void init()
{
setSize(300, 300);
table = new Table(this);
player = new Player();
ball = new Ball(180, 175); // set the ball's initial position in the arguments
miosoft = new Miosoft();
miocare = new Miocare();
miowipe = new Miowipe();
miofresh = new Miofresh();
mioboost = new Mioboost();
setContentPane(table); // makes our graphical JPanel container the content pane for the Applet
// createGUI(); // this has been moved onto the table class
}
public void stop()
{
}
// little getters to make things easier on the table
public int getBallX()
{
return ball.getXPosition();
}
public int getBallY()
{
return ball.getYPosition();
}
public int getLives()
{
return player.getLives();
}
public int getScore()
{
return player.getScore();
}
}
And here is the table class
import java.awt.*; // needed for old style graphics stuff
import java.awt.geom.AffineTransform;
import java.awt.geom.RoundRectangle2D;
import java.awt.image.BufferedImage;
import javax.imageio.ImageIO;
import javax.swing.*; // gives us swing stuff
import sun.rmi.transport.LiveRef;
import java.io.IOException;
import java.net.*; // useful for anything using URLs
/*--------------------------------------------------------------
Auto-generated Java code for class Table
Generated by QSEE-SuperLite multi-CASE, QSEE-Technologies Ltd
www.qsee-technologies.com
Further developed to be the Content pane of this application by Craig Brett
----------------------------------------------------------------*/
public class Table extends JPanel
{
// attributes go here
Pinball pb;
Color bgColour;
Color launcherColour;
Color ballColour;
Image logo;
Image freshBonus;
Image midCircle;
Image leftBumper;
Image rightBumper;
Image nappy1;
Image nappy2;
Image nappy3;
int ballX;
int ballY;
int playerLives;
int playerScore;
// constructor goes here
public Table(Pinball pb)
{
setPreferredSize(new Dimension(300, 300));
this.pb = pb;
// this is not needed anymore, with the new loadImage class down the bottom
// Toolkit tk = Toolkit.getDefaultToolkit(); // needed to get images
// logo = tk.getImage(base + "images/bambinomio.jpg");
logo = loadImage("bambinomio.jpg");
freshBonus = loadImage("miofresh circle.jpg");
midCircle = loadImage("middle circle.jpg");
leftBumper = loadImage("left bumper.jpg");
rightBumper = loadImage("right bumper.jpg");
nappy1 = loadImage("nappy1.jpg");
nappy2 = loadImage("nappy2.jpg");
nappy3 = loadImage("nappy3.jpg");
createGUI();
}
// public methods go here
// all GUI creation stuff goes here
public void createGUI()
{
// setting the background colour
bgColour = new Color(190, 186, 221); // makes the sky blue colour for the background.
setBackground(bgColour);
launcherColour = new Color(130, 128, 193);
ballColour = new Color(220, 220, 220); // the color of the launch spring and ball
// setOpaque(false);
}
public void paintComponent(Graphics g)
{
super.paintComponent(g);
// to give us access to the 2D graphics features
Graphics2D g2d = (Graphics2D) g;
// creating the panels
g2d.setColor(Color.WHITE);
g2d.fillRect(200, 20, 100, 280); // the logo Panel
g2d.fillRect(0, 0, 300, 20);
g2d.setColor(Color.BLACK);
g2d.drawRoundRect(230, 125, 40, 120, 20, 20); // the lives panel
g2d.drawRoundRect(210, 255, 80, 40, 20, 20);
g2d.drawString("Score", 215, 270);
g2d.drawString(displayScore(), 215, 290);
// now drawing the graphics
g2d.drawImage(logo, 205, 25, 90, 90, null);
g2d.drawImage(freshBonus, 10, 40, 20, 20, this);
g2d.drawImage(leftBumper, 40, 200, 10, 20, this);
g2d.drawImage(rightBumper, 150, 200, 10, 20, this);
// now the three mid circles
g2d.drawImage(midCircle, 55, 120, 25, 25, this);
g2d.drawImage(midCircle, 95, 90, 25, 25, this);
g2d.drawImage(midCircle, 95, 150, 25, 25, this);
// now filling out the lives depending on how many the players have
playerLives = pb.getLives();
if(playerLives >= 1)
g2d.drawImage(nappy1, 235, 135, 32, 30, this);
if(playerLives >= 2)
g2d.drawImage(nappy2, 235, 170, 32, 30, this);
if(playerLives >= 3)
g2d.drawImage(nappy3, 235, 205, 32, 30, this);
// now to handle the white lines
g2d.setColor(Color.WHITE);
g2d.drawLine(20, 250, 20, 60); // the left edge
g2d.drawArc(10, 40, 20, 20, 45, 225); // the top left corner
g2d.drawLine(28, 43, 160, 43); // the top of the table
g2d.drawArc(150, 41, 40, 30, 0, 120); // the top right corner
g2d.drawLine(20, 250, 35, 270); // the bottom left corner
// now for the launcher, we draw here
g2d.setColor(launcherColour);
g2d.fillRoundRect(170, 75, 30, 175, 20, 20); // the blue tube
g2d.setColor(ballColour);
g2d.fillRoundRect(175, 210, 20, 40, 20, 20); // the first bit of the launcher
g2d.fillRect(175, 210, 20, 20); // the top of the launcher's firer
g2d.fillRoundRect(175, 195, 20, 10, 20, 20); // the bit that hits the ball
// now drawing the ball wherever it is
ballX = pb.getBallX();
ballY = pb.getBallY();
g2d.fillOval(ballX, ballY, 10, 10);
// now the flippers
g2d.setPaint(Color.WHITE);
// more precise coordinates can be given when the transformation below works
// RoundRectangle2D leftFlipper = new RoundRectangle2D.Double(43.0, 245.0, 20.0, 50.0, 30.0, 30.0); // have to make this using shape parameters
// now using Affine Transformation to rotate the rectangles for the flippers
AffineTransform originalTransform = g2d.getTransform();
AffineTransform transform = AffineTransform.getRotateInstance(Math.toRadians(120));
g2d.transform(transform); // apply the transform
g2d.fillRoundRect(33, 260, 20, 40, 10, 10);
g2d.setTransform(originalTransform); // resetting the angle
// g2d.drawString("The flipper should be drawn", 80, 130); // for debugging if the previous draw instructions have been carried out
}
// a little useful method for handling loading of images and stuff
public BufferedImage loadImage(String filename)
{
BufferedImage image = null;
try
{
URL url = new URL(pb.getCodeBase(), "images/" + filename);
image = ImageIO.read(url);
}catch(IOException e)
{
System.out.println("Error loading image - " + filename + ".");
}
return image;
}
private String displayScore()
{
playerScore = pb.getScore();
String scoreString = Integer.toString(playerScore);
String returnString = "";
if(scoreString.length() < 8)
{
for(int i = 0; i < (8 - scoreString.length()); i++)
{
returnString = returnString + "0";
}
}
returnString = returnString + scoreString;
return returnString;
}
}
Normally to rotate something, you rotate it around some point of interest (the anchor point of the thing that is rotating), not the point 0,0. It appears you are rotating around 0, 0 so chances are this is getting rotated off the screen. To rotate around an arbitrary point, first translate that point to 0 (negative translation) then rotate, then do translate back (postive translation).