I make a game in java and I can't seem to call the paintComponent() method in my game. here's the code :
public class TwinMoonTowers extends JPanel implements ActionListener{
private class TMTMenu extends MouseAdapter{
private Icon start, shop, quit;
private Icon main_bg;
public TMTMenu (){
System.out.println("starting menu...");
start = new Icon(TMTConstant.START_SOURCE,
TMTConstant.START_COORD_X, TMTConstant.START_COORD_Y);
shop = new Icon (TMTConstant.SHOP_SOURCE,
TMTConstant.SHOP_COORD_X, TMTConstant.SHOP_COORD_Y);
quit = new Icon (TMTConstant.EXIT_SOURCE,
TMTConstant.EXIT_COORD_X, TMTConstant.EXIT_COORD_Y);
main_bg = new Icon (TMTConstant.MAIN_MENU_BG, 0, 0);
}
#Override
public void mousePressed(MouseEvent me){
int x = me.getX();
int y = me.getY();
System.out.println("coord: "+x+","+y);
if (me.getButton() == MouseEvent.BUTTON1){
if (x > start.x && x < start.x + start.getIcon().getWidth(null)
&& y > start.y && y < start.y + start.getIcon().getHeight(null)){
curState = TMTConstant.MODE_STATE;
}
else if (x > quit.x && x < quit.x + quit.getIcon().getWidth(null)
&& y > quit.y && y < quit.y + quit.getIcon().getHeight(null)){
curState = TMTConstant.EXIT_STATE;
}
else if (x > shop.x && x < shop.x + shop.getIcon().getWidth(null)
&& y > shop.y && y < shop.y + shop.getIcon().getHeight(null)){
curState = TMTConstant.SHOP_STATE;
}
}
}
}
private class TMTModeSelector extends MouseAdapter{
private Icon TwinTower, TripleTower, back;
public TMTModeSelector(){
}
#Override
public void mousePressed(MouseEvent e){
}
}
private String testDebug;
private int curState;
private TMTMenu menu;
public TwinMoonTowers (){
menu = new TMTMenu();
curState = TMTConstant.MAIN_MENU_STATE;
System.out.println("creating panel..");
this.setVisible(true);
this.setDoubleBuffered(true);
this.setSize(TMTConstant.WINDOW_WIDTH, TMTConstant.WINDOW_HEIGHT);
this.addMouseListener(menu);
}
#Override
public void actionPerformed(ActionEvent arg0) {
// TODO Auto-generated method stub
this.repaint();
}
#Override
public void paintComponent (Graphics g){
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
System.out.println("preparing canvas..");
switch(curState){
case TMTConstant.MAIN_MENU_STATE :
g2d.drawImage(menu.main_bg.getIcon(), menu.main_bg.x, menu.main_bg.y, this);
g2d.drawImage(menu.start.getIcon(), menu.start.x, menu.start.y, null);
g2d.drawImage(menu.quit.getIcon(), menu.quit.x, menu.quit.y, null);
g2d.drawImage(menu.shop.getIcon(), menu.shop.x, menu.shop.y, null);
break;
case TMTConstant.GAME_STATE :
break;
case TMTConstant.SHOP_STATE :
break;
case TMTConstant.MODE_STATE :
break;
}
System.out.print("render image...");
Toolkit.getDefaultToolkit().sync();
g.dispose();
}
}
while class Icon is this:
public class Icon{
private Image pic;
public int x, y;
public Icon (String path, int x, int y){
ImageIcon ii = new ImageIcon (path);
pic = ii.getImage();
this.x = x;
this.y = y;
}
public Image getIcon() {return pic;}
}
the basics here is to draw a menu containing 3 buttons (start, shop, exit)
but, the paintComponent method is not called (the system.out.println not showing)
Toolkit.getDefaultToolkit().sync();
g.dispose();
These lines are unnecessary (might even be wrong), remove them.
The problem is most likely not in the code you posted. Where do you add the panel to a top level window (frame/applet)? What layout do you use for its content pane? My guess is the size is (0,0) so the panel won't be painted.
Related
I am working on homework for class, and its late because I can't seem to understand the material despite all the research that I am doing. I am a beginner and do not know much in the way of java. Also, this is my first post so please be forgiving when you are reading this.
I am building on source code from my textbook, which I updated recently for past homework, but now I am trying to generate a class that draws multiple squares and moves those objects independently and at different speeds. They will all need to rebound off the walls as well. I followed the instructions and created two arrays that will hold the random x and y values between 1 and 10. However, I struggle with arrays and I am sure that I am not doing it correctly. So, I would love some feedback to see if I have it set up correctly.
I have a the jpanel pulling up and drawing, and as long as there is 1 square it is working fine bouncing off the walls, but things change when I draw more than one. The do not move independently and they also share the same speed. Some even disappear from time to time. This has really thrown me off. I appreciate any help!
In short, I am trying to paint new squares that all travel in different directions and at different speeds. Per the instructions we are suppose create and use a two arrays that handle the x and y values.
Here is what I have so far:
public class DotsPanel extends JPanel
{
private int delay = 15;
private final int SIZE = 7, IMAGE_SIZE = 3; // radius of each dot
private Timer timer;
private int x, y, i;
private ArrayList<Point> pointList;
static int [] xarray = new int [1000];
static int [] yarray = new int [1000];
Random rand = new Random();
//-----------------------------------------------------------------
// Constructor: Sets up this panel to listen for mouse events.
//-----------------------------------------------------------------
public DotsPanel()
{
pointList = new ArrayList<Point>();
int [] xarray = new int [1000];
int [] yarray = new int [1000];
timer = new Timer(delay, new ReboundListener());
addMouseListener (new DotsListener());
addMouseMotionListener (new DotsListener());
setBackground(Color.gray);
setPreferredSize(new Dimension(700, 500));
for(int i = 0; i < xarray.length; i++)
{
xarray[i] = rand.nextInt(7);
yarray[i] = rand.nextInt(7);
}
timer.start();
}
//-----------------------------------------------------------------
// Draws all of the dots stored in the list.
//-----------------------------------------------------------------
public void paintComponent(Graphics page)
{
super.paintComponent(page);
page.setColor(Color.BLUE);
for (Point spot : pointList)
{
page.fillRect(spot.x-SIZE, spot.y-SIZE, 25, 25);
page.drawString("Count: " + pointList.size(), 5, 15);
}
}
//*****************************************************************
// Represents the listener for mouse events.
//*****************************************************************
private class DotsListener implements MouseListener, MouseMotionListener
{
//--------------------------------------------------------------
// Adds the current point to the list of points and redraws
// the panel whenever the mouse button is pressed.
//--------------------------------------------------------------
public void mousePressed(MouseEvent event)
{
pointList.add(event.getPoint());
repaint();
}
public void mouseDragged(MouseEvent event)
{
// initially I had two xarray and yarray in here just like in
// mouseClicked
// but it did not change anything when removed
}
//--------------------------------------------------------------
// Provide empty definitions for unused event methods.
//--------------------------------------------------------------
public void mouseClicked(MouseEvent event)
{
xarray[i] = rand.nextInt(7);
yarray[i] = rand.nextInt(7);
}
public void mouseReleased(MouseEvent event) {}
public void mouseEntered(MouseEvent event) {}
public void mouseExited(MouseEvent event) {}
public void mouseMoved(MouseEvent e) {}
}
private class ReboundListener implements ActionListener
{
//--------------------------------------------------------------
// Updates the position of the image and possibly the direction
// of movement whenever the timer fires an action event.
//--------------------------------------------------------------
public void actionPerformed(ActionEvent event)
{
for (Point spot : pointList)
{
spot.x += xarray[i];
spot.y += yarray[i];
if (spot.x <= 0 || spot.x >= 700)
xarray[i] = xarray[i] * -1;
if (spot.y <= 0 || spot.y >= 500)
yarray[i] = yarray[i] * -1;
repaint();
}
}
}
}
However, I struggle with arrays and I am sure that I am not doing it correctly.
I wouldn't use Arrays.
Instead, have a Ball object manage its own state. Then you can have different color, speed, size etc for each Ball. Then when the Timer fires you just calculate the new position and repaint the Ball.
Here is an example to get you started:
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import java.util.*;
import javax.swing.*;
import javax.swing.Timer;
public class BallAnimation4
{
private static void createAndShowUI()
{
BallPanel panel = new BallPanel();
JFrame frame = new JFrame("BallAnimation4");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add( panel );
frame.setSize(800, 600);
frame.setLocationRelativeTo( null );
//frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
frame.setVisible( true );
panel.addBalls(5);
panel.startAnimation();
}
public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable()
{
public void run()
{
createAndShowUI();
}
});
}
}
class BallPanel extends JPanel implements ActionListener
{
private ArrayList<Ball> balls = new ArrayList<Ball>();
public BallPanel()
{
setLayout( null );
setBackground( Color.BLACK );
}
public void addBalls(int ballCount)
{
Random random = new Random();
for (int i = 0; i < ballCount; i++)
{
Ball ball = new Ball();
ball.setRandomColor(true);
ball.setLocation(random.nextInt(getWidth()), random.nextInt(getHeight()));
ball.setMoveRate(32, 32, 1, 1, true);
// ball.setMoveRate(16, 16, 1, 1, true);
ball.setSize(32, 32);
balls.add( ball );
}
}
#Override
public void paintComponent(Graphics g)
{
super.paintComponent(g);
for (Ball ball: balls)
{
ball.draw(g);
}
}
public void startAnimation()
{
Timer timer = new Timer(75, this);
timer.start();
}
public void actionPerformed(ActionEvent e)
{
move();
repaint();
}
private void move()
{
for (Ball ball : balls)
{
ball.move(this);
}
}
class Ball
{
public Color color = Color.BLACK;
public int x = 0;
public int y = 0;
public int width = 1;
public int height = 1;
private int moveX = 1;
private int moveY = 1;
private int directionX = 1;
private int directionY = 1;
private int xScale = moveX;
private int yScale = moveY;
private boolean randomMove = false;
private boolean randomColor = false;
private Random myRand = null;
public Ball()
{
myRand = new Random();
setRandomColor(randomColor);
}
public void move(JPanel parent)
{
int iRight = parent.getSize().width;
int iBottom = parent.getSize().height;
x += 5 + (xScale * directionX);
y += 5 + (yScale * directionY);
if (x <= 0)
{
x = 0;
directionX *= (-1);
xScale = randomMove ? myRand.nextInt(moveX) : moveX;
if (randomColor) setRandomColor(randomColor);
}
if (x >= iRight - width)
{
x = iRight - width;
directionX *= (-1);
xScale = randomMove ? myRand.nextInt(moveX) : moveX;
if (randomColor) setRandomColor(randomColor);
}
if (y <= 0)
{
y = 0;
directionY *= (-1);
yScale = randomMove ? myRand.nextInt(moveY) : moveY;
if (randomColor) setRandomColor(randomColor);
}
if (y >= iBottom - height)
{
y = iBottom - height;
directionY *= (-1);
yScale = randomMove ? myRand.nextInt(moveY) : moveY;
if (randomColor) setRandomColor(randomColor);
}
}
public void draw(Graphics g)
{
g.setColor(color);
g.fillOval(x, y, width, height);
}
public void setColor(Color c)
{
color = c;
}
public void setLocation(int x, int y)
{
this.x = x;
this.y = y;
}
public void setMoveRate(int xMove, int yMove, int xDir, int yDir, boolean randMove)
{
this.moveX = xMove;
this.moveY = yMove;
directionX = xDir;
directionY = yDir;
randomMove = randMove;
}
public void setRandomColor(boolean randomColor)
{
this.randomColor = randomColor;
switch (myRand.nextInt(3))
{
case 0: color = Color.BLUE;
break;
case 1: color = Color.GREEN;
break;
case 2: color = Color.RED;
break;
default: color = Color.BLACK;
break;
}
}
public void setSize(int width, int height)
{
this.width = width;
this.height = height;
}
}
}
Since your Arrays only contain the Point you want to paint you don't have any information about the speed each point should be moved at. The best you could do is create a random amount each point should be moved each time its location is changed. This would give erratic movement as each time you move a point the distance would be random.
If you want more constant speed then you would need to create a second Array to contain the distance each point should move every time.
This starts to get messy creating a new Array every time you want a new property to be unique for the object you want to paint. That is why the approach to create a custom Object with multiple properties is easier to manage.
So I have two classes here:
PhotoComponent class:
(This class is to handle a specific image as a JComponent. When "flipped" I want to draw pen strokes instead of having an image. So I replace the image with a rectangle, attempting to draw pen strokes over it.)
public class PhotoComponent extends JComponent {
private Image pic;
private boolean flipped;
private int contentAreaWidth;
private int contentAreaHeight;
p
#Override
public void paintComponent(Graphics g) {
//Does all the drawing and contains whatever state information is associated with the photo
//create an action event to auto call repaint
//call repaint anytime flip was changed to true or false
System.out.println("Draw: " + draw + ", Pic: " + pic);
if (draw && pic != null) {
super.paintComponent(g);
System.out.println("width using this: " + this.getWidth() + ", actual width of JPanel: " + contentAreaWidth);
System.out.println("height using this: " + this.getHeight() + ", actual height of JPanel: " + contentAreaHeight);
g2 = (Graphics2D) g;
int x = (contentAreaWidth - pic.getWidth(null)) / 2;
int y = (contentAreaHeight - pic.getHeight(null)) / 2;
if (!flipped) {
g2.drawImage(pic, x, y, null);
} else if (flipped) {
g2.setColor(Color.WHITE);
g2.fillRect(x,y,pic.getWidth(null), pic.getHeight(null));
g2.drawRect(x, y, pic.getWidth(null), pic.getHeight(null));
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
if (drawingMode) {
g2.setPaint(Color.RED);
if (drawOval) {
penStrokes.put(ovalX, ovalY);
if (penStrokes != null) {
for (Integer xCoor : penStrokes.keySet()) {
g2.setPaint(Color.RED);
int brushSize = 5;
g2.fillOval((xCoor - (brushSize / 2)), (penStrokes.get(xCoor) - (brushSize / 2)), brushSize, brushSize);
//System.out.println("SIZE OF HASHTABLE: " + penStrokes.size());
}
}
System.out.println("Filling an oval!" + ovalX + ", " + ovalY);
}
} else if (textMode) {
g2.setPaint(Color.YELLOW);
if (drawRect) {
rectDimensions.add(rectX);
rectDimensions.add(rectY);
rectDimensions.add(rectWidth);
rectDimensions.add(rectHeight);
for (int i = 0; i < rectDimensions.size(); i+=4) {
g2.fillRect(rectDimensions.get(i), rectDimensions.get(i+1), rectDimensions.get(i+2), rectDimensions.get(i+3));
g2.drawRect(rectDimensions.get(i), rectDimensions.get(i+1), rectDimensions.get(i+2), rectDimensions.get(i+3));
}
}
}
System.out.println("This is being called again!");
}
}
}
public void setRectangle(int x, int y, int width, int height) {
drawRect = true;
rectX = x;
rectY = y;
rectWidth = width;
rectHeight = height;
}
public void removeRectangle() {
drawRect = false;
}
public int[] setOval(int currentX, int currentY) {
drawOval = true;
int[] toReturn = {ovalX, ovalY};
ovalX =
NOTE THE DRAWLINE() METHOD ABOVE. I am drawing at the given points, repainting, and setting the old variables to be the current variables.
Main class:
private static PhotoComponent img;
private static JFrame frame;
private static JPanel contentArea;
//Mouse Coordinates for PenStrokes
private static int oldX, oldY;
//Mouse Coordinates for Sticky Notes
private static Point clickPoint;
public static void main (String[] args) {
frame = new JFrame("PhotoManip");
img = null;
contentArea = null;
oldX = 0;
oldY = 0;
setupMenubar(frame);
setupJFrame(frame);
}
private static void addPhotoComponent(File file) {
}
if (img.getTextMode()) {
img.removeRectangle();
clickPoint = null;
}
}
});
img.addMouseMotionListener(new MouseAdapter() {
#Override
public void mouseDragged(MouseEvent e) {
if (img.getDrawingMode()) {
if (withinRange(e.getX(), e.getY())) {
int[] toUpdate = img.setOval(e.getX(), e.getY());
oldX = toUpdate[0];
oldY = toUpdate[1];
img.repaint();
}
}
if (img.getTextMode()) {
if (withinRange(e.getX(), e.getY())) {
Point dragPoint = e.getPoint();
h, height);
img.repaint();
}
}
}
});
if (img!=null) {
contentArea.add(img);
}
}
private static boolean withinRange(int x, int y) {
if (x > img.getX() && x < img.getX() + img.getWidth()) {
if (y > img.getY() && y < img.getY() + img.getHeight()) {
return true;
}
}
return false;
}
private static void flipImage() {
if (!img.isFlipped()) {
img.setFlipped(true);
} else if (img.isFlipped()) {
img.setFlipped(false);
}
}
drawLine() is called above in this main class, when a mousedrag occurs. Problem is that the strokes don't appear to show.
I know that the program is calling g2.fillOval() because I am printing out a verification statement afterwards.
Additionally, I have created print statements for when the mouse is pressed and dragged and they are getting the correct coordinates?
Why don't red strokes appear? I'm confused. Is it the way my code is structured?
The crux of your problem is that you are trying to draw something outside the paintComponent method, which is never supported. Whatever you draw will get overwritten by the next call of paintComponent, which will happen almost instantly. We can solve this by storing the co-ordinates of the oval and drawing it within paintComponent instead of trying to draw on a graphics object outside of the paintComponent method. See code below:
First we are going to add the following variables to your PhotoComponent class:
private boolean drawOval = false;
private int ovalX = 0;
private int ovalY = 0;
Then we will add methods for controlling them:
public int[] setOval(int currentX, int currentY) {
drawOval = true;
int[] toReturn = {ovalX, ovalY};
ovalX = currentX;
ovalY = currentY;
return toReturn;
}
public void removeOval() {
drawOval = false;
}
After that we can change the paintComponent method to have it draw the oval based on those variables:
#Override
public void paintComponent(Graphics g) {
//Does all the drawing and contains whatever state information is associated with the photo
//create an action event to auto call repaint
//call repaint anytime flip was changed to true or false
super.paintComponent(g);
g2 = (Graphics2D) g;
int x = (contentAreaWidth - pic.getWidth(null)) / 2;
int y = (contentAreaHeight - pic.getHeight(null)) / 2;
if (!flipped) {
g2.drawImage(pic, x, y, null);
} else if (flipped) {
g2.setColor(Color.WHITE);
g2.fillRect(x, y, pic.getWidth(null), pic.getHeight(null));
g2.drawRect(x, y, pic.getWidth(null), pic.getHeight(null));
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setPaint(Color.RED);
}
//took the code you already used for drawing the oval and moved it here
if (drawOval) {
g2.setPaint(Color.RED);
int brushSize = 5;
g2.fillOval((ovalX - (brushSize / 2)), (ovalY - (brushSize / 2)), brushSize, brushSize);
}
}
Finally change the addPhotoComponent method to update those variables instead of trying to draw the oval directly:
private static void addPhotoComponent(File file) {
Image image = null;
try {
image = ImageIO.read(file);
} catch (IOException e2) {
System.out.println("ERROR: Couldn't get image.");
}
img = new PhotoComponent(image, contentArea);
img.revalidate();
img.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
if (e.getClickCount() == 2) {
// your code here
System.out.println("You flipped the photo!!!");
flipImage();
img.repaint();
}
}
#Override
public void mousePressed(MouseEvent e) {
img.setOval(e.getX(), e.getY());
}
#Override
public void mouseReleased(MouseEvent e) {
img.removeOval();
}
});
img.addMouseMotionListener(new MouseAdapter() {
#Override
public void mouseDragged(MouseEvent e) {
int[] toUpdate = img.setOval(e.getX(), e.getY());
oldX = toUpdate[0];
oldY = toUpdate[1];
}
});
if (img != null) {
contentArea.add(img);
}
}
I have written a program to draw 1 car when I click the mouse button, now I want to draw 1 more car when I click a second time on the mouse button.
#SuppressWarnings("serial")
public class CarMove extends JComponent
{
private volatile boolean drawCar = false;
private volatile boolean drawCar1 = false;
private int lastX = 0;
private int clickCount = 0;
{
FrameMouseListener listener = new FrameMouseListener();
super.addMouseListener(listener);
}
public CarMove()
{
Thread animationThread = new Thread(new Runnable()
{
public void run()
{
while (true)
{
repaint();
try
{
Thread.sleep(10);
} catch (Exception ex) {}
}
}
});
animationThread.start();
}
public void paintComponent(Graphics g)
{
Graphics2D g2 = (Graphics2D) g;
if (drawCar)
{
int x = 1;
int carSpeed = 1;
int w = getWidth();
x = lastX + carSpeed;
//create the car from draw class
Car car1 = new Car(x,320);
car1.draw(g2);
lastX = x;
}
if (drawCar1)
{
int x = 1;
int carSpeed = 1;
int w = getWidth();
x = lastX + carSpeed;
//create the car from draw class
Car car2 = new Car(x,320);
car2.draw(g2);
lastX = x;
}
}
public class FrameMouseListener implements MouseListener
{
#Override
public void mouseClicked(MouseEvent ev)
{
if (clickCount == 1)
{
drawCar = true;
repaint();
}
if (clickCount == 2)
{
drawCar1 = true;
repaint();
}
}
I try to create the boolean drawcar 2 times but It did not work please help me.
In case you need to know how many times the user clicked the mouseButton.
#Override
public void mouseReleased(MouseEvent m) {
int clickCount = m.getClickCount();
//change your code to do draw the cars based on clicks
}
Edit:
when you call repaint method always the first line must be:
super.repaint();
To draw multiple cars you have to use a loop when you call the paint(Graphics g) like:
public void paintComponent(Graphics g){
super.repaint();
Graphics2D g2 = (Graphics2D) g;
for(int car=0; car<totalClicks; car++){
//Here add your code to draw the cars
if(car==1){
//do this
}else if(car==2){
//do that
}else if(car== 3){
//do more
}else if(car==4){
//hard job
}//etc
}
Well when I am pressing any of the key arrows, the red box moves, yes it moves 10px and then stops for 1 second & continues moving, instead of move right away without stopping.
example of the occurring issue:
(source: gyazo.com)
Can you see how it stopped for 1 or 0.5 secs and continued?
How can I fix it?
I am using KeyEventDispatcher
My key detecting:
Whole src:
public class Game extends Frame {
private class Keyboard implements KeyEventDispatcher {
private Game game;
public Keyboard(Game game) {
this.game = game;
}
#Override
public boolean dispatchKeyEvent(KeyEvent e) {
if (e.getID() == KeyEvent.KEY_PRESSED) {
this.movement(e);
} else if (e.getID() == KeyEvent.KEY_RELEASED) {
} else if (e.getID() == KeyEvent.KEY_TYPED) {
}
return false;
}
public void movement(KeyEvent e) {
int keyCode = e.getKeyCode();
switch( keyCode ) {
case KeyEvent.VK_UP:
game.movePlayer(0, -10);
break;
case KeyEvent.VK_DOWN:
game.movePlayer(0, 10);
break;
case KeyEvent.VK_LEFT:
game.movePlayer(-10, 0);
break;
case KeyEvent.VK_RIGHT :
game.movePlayer(10, 0);
break;
}
}
}
private static final long serialVersionUID = 1L;
private int coordinateX = 1;
private int coordinateY = 1;
public int width = 300;
public int height = width / 16 * 9;
public int scale = 3;
public int mouseY = MouseInfo.getPointerInfo().getLocation().y;
public int mouseX = MouseInfo.getPointerInfo().getLocation().x;
private Player player = new Player(0, 0);
public Game() {
Dimension size = new Dimension(width * scale, height * scale);
setPreferredSize(size);
frame.setSize(width, height);
frame.setResizable(false);
frame.setTitle("First game");
JPanel j = new JPanel();
j.setVisible(true);
JLabel text = new JLabel("coords");
j.add(text);
frame.add(this);
frame.pack();
frame.add(j);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager();
manager.addKeyEventDispatcher(new Keyboard(this));
}
private void movePlayer(int x, int y) {
/**
* Main region area
*/
int pX = 0, pY = 0;
if (y == 0) { // x
if (player.getX() + x + 100 > frame.getContentPane().getWidth() || player.getX() + x < 0) {
if (player.getX() + x < 0) {
player.setX(0);
return;
}
if (player.getX() + x > 0) {
player.setX(frame.getContentPane().getWidth() - 100);
return;
}
return;
}
pX = x;
}
else if (x == 0) { // y
if (player.getY() + y + 100 > frame.getContentPane().getHeight() || player.getY() + y < 0) {
if (player.getY() + y < 0) {
player.setY(0);
return;
}
if (player.getY() + y > 0) {
player.setY(frame.getContentPane().getHeight() - 100);
return;
}
return;
}
pY = y;
}
player.updatePosition(pX, pY);
}
public void update() {
}
public void render() {
bs = getBufferStrategy();
if (bs == null) {
createBufferStrategy(3);
return;
}
g = bs.getDrawGraphics();
g.setColor(Color.BLACK);
g.fillRect(0, 0, getWidth(), getHeight());
g.setColor(Color.RED);
g.fillRect(player.getX(), player.getY(), 100, 100);
g.dispose();
bs.show();
}
}
Frame.java:
public class Frame extends Canvas {
public static final long serialVersionUID = 8L;
public static JFrame frame = new JFrame();
public static Threads thread;
public static Game game;
public Graphics g;
public BufferStrategy bs;
/**
* #param args
*/
public static void main(String[] args) {
thread = new Threads(new Game());
thread.start();
}
}
The problem is the repeat rate for KeyStrokes. This is controlled by the OS.
The solution is to use a Swing Timer to schedule the animation as soon as the key is pressed.
See Motion Using the Keyboard for more information and a complete working example.
Also, you should NOT be using a KeyListener but intead should be using KeyBindings.
I want to creat a circle in on a panel which appears and dissapears every 2 seconds.
Here is that i have:
public class Board extends JPanel implements ActionListener {
private final int DELAY = 2000;
private Timer timer;
/*
* constructor
*/
public Board() {
setFocusable(true);
initGame();
}
/*
* initialize board
*/
public void initGame() {
timer = new Timer(DELAY, this);
timer.start();
}
public void paint(Graphics g) {
super.paint(g);
g.setColor(Color.gray);
// draw an oval starting at 20,20 with a width and height of 100 and
// fill it
g.drawOval(20, 20, 100, 100);
g.fillOval(20, 20, 100, 100);
g.dispose();
}
#Override
public void actionPerformed(ActionEvent e) {
repaint();
}
}
thank you guys. Now I wanna control my circle. But again something is wrong and it is not moving as I want.
here are new methods:
private boolean left = false;
private boolean right = true;
private boolean up = false;
private boolean down = false;
private Timer timer;
public int x = 20;
public int y = 20;
public int x2 = 100;
public int y2 = 100;
...
public void paint(Graphics g) {
super.paint(g);
if (drawCircle) {
g.setColor(Color.gray);
// draw an oval starting at 20,20 with a width and height of 100 and
// fill it
g.drawOval(x, y, x2, y2);
g.fillOval(x, y, x2, y2);
}
// removes native non-Java recourses
g.dispose();
}
public void move() {
if (left) {
x -= 5;
}
if (right) {
x += 5;
}
if (up) {
y -= 5;
}
if (down) {
y += 5;
}
}
#Override
public void actionPerformed(ActionEvent e) {
move();
repaint();
}
private class TAdapter extends KeyAdapter {
public void keyPressed(KeyEvent e) {
int key = e.getKeyCode();
if ((key == KeyEvent.VK_LEFT) && (!right)) {
left = true;
up = false;
down = false;
}
if ((key == KeyEvent.VK_RIGHT) && (!left)) {
right = true;
up = false;
down = false;
}
if ((key == KeyEvent.VK_UP) && (!down)) {
up = true;
right = false;
left = false;
}
if ((key == KeyEvent.VK_DOWN) && (!up)) {
down = true;
right = false;
left = false;
}
}
}
/****/
Solved , i just added
addKeyListener(new TAdapter());
to my Board constructor!
You just need to have your Timer modify some state. Try something like this:
private boolean drawCircle = false;
public void actionPerformed(ActionEvent e) {
drawCircle = !drawCircle;
repaint();
}
public void paintComponent(Graphics g) {
//...
if ( drawCircle ) {
g.setColor(Color.gray);
//...
}
}
Aren't you supposed to formulate the question... as a question?
Anyway, add a boolean to your class, toggle it on each action event, and paint the oval only if it is true.
Edit/Notes:
- Override paintComponent instead of paint
- Don't dispose of a Graphics you haven't created. Either drop the line, or use g.create() to make a copy. See http://java.sun.com/products/jfc/tsc/articles/swing2d/ for details.