I'm trying to make an animated screensaver with some changing colors and moving shapes and I also want it to have a sort of trail effect (like how the most recent color on each pixel is continually drawn there if you don't set your background color). I achieved this effect once before, but I don't know how I did it. Currently the result is a moving square with that changes colors across a grey background.
ScreenSaver.java
import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JPanel;
import javax.swing.Timer;
public class ScreenSaver extends JPanel
{
public static Component sc;
public int delay = 1000/2;
public int state = 0;
public int re = 255;
public int gr = 0;
public int bl = 0;
public int d = 1;
ScreenSaver()
{
ActionListener counter = new ActionListener()
{
public void actionPerformed(ActionEvent event)
{
updateUI();
repaint();
}
};
new Timer(delay, counter).start();
System.out.println("this is the secret screensaver that appears after 30 seconds of no mouse activity");//i have this line here so it doesn't print every time the screen updates
}
public void paintComponent(Graphics g)
{
super.paintComponent(g);
this.setBackground(null);
if (state == 0)
{
gr++;
if(gr == 255)
state = 1;
}
if (state == 1)
{
re--;
if(re == 0)
state = 2;
}
if (state == 2)
{
bl++;
if(bl == 255)
state = 3;
}
if (state == 3)
{
gr--;
if(gr == 0)
state = 4;
}
if (state == 4)
{
re++;
if(re == 255)
state = 5;
}
if (state == 5)
{
bl--;
if(bl == 0)
state = 0;
}
g.setColor(new Color(re, gr, bl));
d++;
g.fillRect(d, 50, 50, 50);
}
public static void main(String[] args)
{
//ScreenSaver sc = new ScreenSaver();
}
}
Main.java: (ScreenSaver.java is called as an object through this file)
import java.awt.Color;
import java.awt.Graphics;
//import java.util.Random;
//import javax.swing.AbstractAction;
//import javax.swing.Action;
import javax.swing.JFrame;
import javax.swing.JPanel;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import javax.swing.Timer;
public class FinalProject extends JPanel implements MouseMotionListener
{
public int delay = 1000/2;
public boolean screenActive = true;
public int why = 1;
FinalProject()
{
ActionListener counter = new ActionListener()
{
public void actionPerformed(ActionEvent event)
{
updateUI();
repaint();
}
};
new Timer(delay, counter).start();
}
static JFrame jf = new JFrame();
public void paintComponent(Graphics g)
{
super.paintComponent(g);
this.setBackground(Color.BLACK);
if (screenActive)
{
why++;
}
if (why == 6)
{
why = 0;
System.out.println("inactivity detected");
screenActive = false;
ScreenSaver sc = new ScreenSaver();
jf.add(sc);
}
}
public static void main(String[] args) throws InterruptedException
{
System.out.println("Welcome to Computer Simulator 0.1");
System.out.println("this is the main screen");
FinalProject e = new FinalProject();
//ScreenSaver sc = new ScreenSaver();
jf.setTitle("game");
jf.setSize(500,500);
//jf.setUndecorated(true);
//jf.setBackground(new Color(1.0f,1.0f,1.0f,0.5f));
jf.setVisible(true);
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//jf.add(new ScreenSaver());
jf.add(e);
}
#Override
public void mouseDragged(MouseEvent arg0) {
// TODO Auto-generated method stub
}
#Override
public void mouseMoved(MouseEvent MOUSE_MOVED)
{
}
}
Don't invoke updateUI(). All you need is the repaint() to cause the component to repaint itself.
One way it to do the drawing to a BufferedImage and then use the BufferedImage to create an ImageIcon which you add to a JLabel.
The other way is to keep a list of object that you want to paint and then just iterate through the list each time the component is repainted.
Check out Custom Painting Approches for working examples and an analysis of when you might use either approach.
Related
I have been working on this snake project, and dont really understand why the keylistener isnt actually changing the variable char key. I have some other examples of keylisteners, and they all work properly, but for some reason mine isnt working. Some help would be appreciated. Thanks a lot for the help.
import java.awt.Color;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.Toolkit;
import java.awt.event.KeyListener;
import java.awt.geom.Ellipse2D;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.RepaintManager;
public class Main extends JPanel implements Runnable {
/*
*
* SIZE OF BOARD
*
*/
static GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
static GraphicsDevice[] gs = ge.getScreenDevices();
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
private static final int DIM_WIDTH = Toolkit.getDefaultToolkit().getScreenSize().width;
private static final int DIM_HEIGHT = Toolkit.getDefaultToolkit().getScreenSize().height;
static JFrame frame = new JFrame();
static JPanel panel = new JPanel();
static Snake s = new Snake();
static Main main = new Main();
KeyListener listener = new Snake();
boolean black = true;
public Main() {
addKeyListener(listener);
}
#SuppressWarnings("deprecation")
public static void main(String[] args) {
//gs[0].setFullScreenWindow(frame);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setCursor(Cursor.CROSSHAIR_CURSOR);
frame.setSize(DIM_WIDTH, DIM_HEIGHT);
frame.add(main);
frame.setVisible(true);
(new Thread(new Main())).start();
}
// paints the panel
public void paint(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
/*
* Snake
*/
//Redraws Background
g2d.setColor(Color.black);
g2d.fillRect(0, 0, (int) screenSize.getWidth(), (int) screenSize.getHeight());
//Draws Border
g2d.setColor(Color.white);
g2d.fillRect(0,0, (int)screenSize.getWidth(), 1);
g2d.fillRect(0,0, 1, (int)screenSize.getHeight());
g2d.fillRect((int)screenSize.getWidth()-1, 1, 1, (int)screenSize.getHeight());
g2d.fillRect(0, (int)screenSize.getHeight()-86, (int)screenSize.getWidth(), 10);
//Draws Snake head
g2d.setColor(s.getColor());
g2d.fillRect(s.getX(), s.getY(), 30, 30);
}
// Creates Frame, and starts the game
#Override
public void run() {
while (!s.getIsDead()) {
move();
}
}
public void move() {
s.move();
s.death();
main.repaint();
try {
Thread.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (Thread.interrupted()) {
return;
}
}
}
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Toolkit;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
public class Snake implements KeyListener {
Color c = Color.green;
//Starting position of Snake
int x = 50;
int y = 50;
char key;
boolean dead = false;
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
public void move() {
x++;
}
public void death() {
if (x + 30 >= screenSize.getWidth() || y + 115 >= screenSize.getHeight() || y<=0 || x<=0) {
c = Color.red;
dead = true;
}
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public Color getColor() {
return c;
}
public boolean getIsDead() {
return dead;
}
#Override
public void keyTyped(KeyEvent e) {
// TODO Auto-generated method stub
}
#Override
public void keyPressed(KeyEvent e) {
key = 'w';
}
#Override
public void keyReleased(KeyEvent e) {
// TODO Auto-generated method stub
}
}
Change your constructor to
public Main() {
addKeyListener(listener);
setFocusable(true);
requestFocus();
}
But take a look at this question, you should not use KeyListeners.
java keylistener not called
As #azurefrog mentioned, your keyPressed method is setting key to 'w' every time. You need to use the KeyEvent passed in as a parameter to that method to get the key that was pressed. Your keyPressed method should look something like this:
#Override
public void keyPressed(KeyEvent e) {
key = e.getKeyChar();
}
I am trying to implement a jumping square. The square should not be able to jump several times like in flappy bird but have to return on its baseYPosition or - to be implemented later - on a platform(simple GeometryDash clone for a school project).
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.JPanel;
import javax.swing.Timer;
public class Square extends JPanel implements ActionListener, KeyListener{
/**
*
*/
private static final long serialVersionUID = 1L;
private int threadDelay = 40;
public int squareYPosition = 400,squareXPosition = 400, baseYPosition = 400;
public int jumpyness = 40, gravity=3, ySpeed, counter = 0;
public boolean isJumping;
public Square(){
Timer t = new Timer(threadDelay, this);
t.start();
}
public void paintComponent(Graphics g){
super.paintComponent(g);
g.fillRect(squareXPosition, squareYPosition, 40, 40);
}
public void jump(){
ySpeed = jumpyness;
System.out.println("squareYPosition before while: "+squareYPosition);
System.out.println("jumping before?"+isJumping);
if(!isJumping){
isJumping = true;
System.out.println("was not jumping before?"+isJumping);
new Thread(){
#Override
public void run(){
while(isJumping && (ySpeed!=0 || squareYPosition < baseYPosition)){
if(squareYPosition < 0){
ySpeed=-1;
squareYPosition = 0 ;
}
System.out.println("squareYPosition: "+squareYPosition+" . ySpeed: "+ySpeed);
if(squareYPosition-ySpeed > baseYPosition && counter>(jumpyness/gravity)){
squareYPosition = baseYPosition;
ySpeed = 0;
counter = 0;
isJumping = false;
System.out.println("set ySpeed to 0");
}
else{
squareYPosition = squareYPosition - ySpeed;
ySpeed = ySpeed - gravity;
counter++;
}
try {
Thread.sleep(threadDelay);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
}
}
#Override
public void actionPerformed(ActionEvent e) {
repaint();
}
#Override
public void keyPressed(KeyEvent e) {
switch (e.getKeyCode()){
case KeyEvent.VK_SPACE:
this.jump();
break;
case 38:
this.jump();
break;
}
}
#Override
public void keyReleased(KeyEvent e) {}
#Override
public void keyTyped(KeyEvent e) {}
}
The Square class is instantiated in and added to a JFrame.
MainFrame.java
import java.awt.Color;
import java.awt.Dimension;
import java.awt.DisplayMode;
import java.awt.GraphicsDevice;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class MainFrame extends JFrame{
/**
*
*/
private static final long serialVersionUID = 1L;
private Square square;
public MainFrame(String text, GraphicsDevice device, DisplayMode displayMode){
setTitle(text);
setUndecorated(true);
square = new Square();
add(square);
//pack();
setVisible(true);
device.setFullScreenWindow(this);
device.setDisplayMode(displayMode);
repaint();
addKeyListener(square);
}
}
PeterTest.java
import java.awt.Color;
import java.awt.DisplayMode;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.util.Timer;
import java.util.TimerTask;
public class PeterTest {
static long revalidateDelay = 30;
static final int ELEMENTESTART = 3; // Elemente +1 f�r L�cken/abstand oben/unten
public static void main(String[] args) {
GraphicsEnvironment enivronment = GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsDevice device = enivronment.getDefaultScreenDevice();
DisplayMode[] ds = device.getDisplayModes();
//The following is necessary because Unix and Windows have reversed orders in DisplayMode
int highestResolutionIndex = getHighestResolutionIndex(ds);
DisplayMode displayMode = new DisplayMode(ds[highestResolutionIndex].getWidth(), ds[highestResolutionIndex].getHeight(), ds[highestResolutionIndex].getBitDepth(), ds[highestResolutionIndex].getRefreshRate());
MainFrame frame = new MainFrame("Test", device, displayMode);
//
}
public static int getHighestResolutionIndex(DisplayMode[] ds){
long pixels = ds[ds.length-1].getWidth() * ds[ds.length-1].getHeight();
int highestResolutionIndex = 0;
for(int i = 0; i<ds.length; i++){
long newpixels = ds[i].getWidth() * ds[i].getHeight();
if(newpixels>=pixels){
highestResolutionIndex = i;
pixels = newpixels;
}
}
return highestResolutionIndex;
}
}
The boolean isJumping should prevent the thread to be opened while there is another thread for the jumping, but holding the space key will let the square hit the top of the frame. Even locking the boolean will not work for me. I have no idea how to fix this :(
Please help me :'(
Found the problem myself. It hurts. The problem was setting the ySpeed to jumpyness in the first line of jump() and not in the thread before the while.
Hi I'm using the Timer class and the repaint method for the JPanel, but whenever I hit DOWN and the space ship moves halfway down the screen, it shrinks and stays in place. It never reaches the bottom of the window. It is the same when I move it to the RIGHT.
Also when I try to place it in a differnt y position, the background isn't black anymore. Can someone help me with this please? Here is a sample of my code:
package javapaint;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
public class SpaceShipFlight
{
private JFrame windowFrame;
private BufferedImage shipSprite;
private BufferedImage spaceBackground;
/** MAIN METHOD **/
public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable()
{
public void run()
{
try
{
SpaceShipFlight window = new SpaceShipFlight();
window.windowFrame.setVisible(true);
}
catch (Exception e)
{
e.printStackTrace();
}
}
});
}
/** CONSTRUCTOR **/
public SpaceShipFlight() throws IOException
{
/*************************************************************************
SPACE SHIP FLIGHT JFRAME
*************************************************************************/
windowFrame = new JFrame("Space Ship Flight");
windowFrame.setBounds(0, 0, 950, 700);
windowFrame.setBackground(Color.BLACK);
/*************************************************************************
SPACE SHIP FLIGHT SPRITES (FOR DRAWING)
*************************************************************************/
spaceBackground = ImageIO.read(new File("Space (Medium).png"));
// 450 x 374
shipSprite = ImageIO.read(new File("Ship Sprite.png"));
// 64 x 64 png of space ship
/*************************************************************************
SPACE SHIP FLIGHT JPANEL (FOR DRAWING)
*************************************************************************/
SpacePanel spacePanel = new SpacePanel();
windowFrame.add(spacePanel);
/*************************************************************************
SPACE SHIP FLIGHT TIMER
*************************************************************************/
Timer timer = new Timer(10, new AnimationListener(spacePanel));
timer.start();
/*************************************************************************
EVENT HANDLER TO MOVE SPACE SHIP
*************************************************************************/
/*
EventHandler <KeyEvent> moveShip = new EventHandler<KeyEvent> ()
{
#Override
public void handle(KeyEvent event)
{
if (event.getCharacter().equalsIgnoreCase("X"))
{
spacePanel.setX( spacePanel.getX() + 1 );
}
}
};
*/
KeyListener moveShip = new KeyListener()
{
#Override
public void keyTyped(KeyEvent e)
{
}
#Override
public void keyPressed(KeyEvent e)
{
if (e.getKeyCode() == KeyEvent.VK_RIGHT && spacePanel.getX() < 375)
{
spacePanel.setX( spacePanel.getX() + 5 );
spacePanel.repaint();
}
if (e.getKeyCode() == KeyEvent.VK_LEFT && spacePanel.getX() > 0)
{
spacePanel.setX( spacePanel.getX() - 5);
spacePanel.repaint();
}
if (e.getKeyCode() == KeyEvent.VK_UP && spacePanel.getY() > 0)
{
spacePanel.setY( spacePanel.getY() - 5);
spacePanel.repaint();
}
if (e.getKeyCode() == KeyEvent.VK_DOWN && spacePanel.getY() < 700)
{
spacePanel.setY( spacePanel.getY() + 5 );
spacePanel.repaint();
}
if (e.getKeyCode() == KeyEvent.VK_X)
{
System.out.printf("X: %d, Y: %d\n", spacePanel.getX(),
spacePanel.getY());
}
}
#Override
public void keyReleased(KeyEvent e)
{
}
};
windowFrame.addKeyListener(moveShip);
}
/** ANIMATION LISTENER CLASS **/
public static class AnimationListener implements ActionListener
{
private SpacePanel panel;
private Graphics graphics;
public AnimationListener(SpacePanel panel)
{
this.panel = panel;
this.graphics = panel.getGraphics();
}
#Override
public void actionPerformed(ActionEvent e)
{
panel.repaint();
}
}
/** SPACE PANEL SUBCLASS **/
public class SpacePanel extends JPanel
{
// Variables for the space ship's position temporarily placed here
private int x;
private int y;
// Constructor
public SpacePanel()
{
super();
x = 0;
y = 0;
}
// Getters
public int getX()
{
return x;
}
public int getY()
{
return y;
}
// Setters
public void setX(int newX)
{
x = newX;
}
public void setY(int newY)
{
y = newY;
}
#Override
public void paint(Graphics g)
{
g.drawImage(spaceBackground, 0, 0, this);
g.drawImage(shipSprite, x, y, this);
}
}
}
Although there are questions similar, I think mine is slightly different because of how I have my code set up. I have a JFrame within my main method. However, I only have JPanel in my constructor. I tried to make some of my variables static so that I could access them in the main method and say, for instance, if the x-coordinate of this graphic plus its width is greater than frame.getWidth().. but that won't work for some reason. I don't want to bombard anyone with code so I will just try to put the main information and if you need more, I'll update it.
package finalProj;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.Timer;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.geom.Ellipse2D;
public class nonaMaingamePractice extends JPanel implements ActionListener, KeyListener {
/**
*
*/
private static final long serialVersionUID = 1L;
private static Ellipse2D ellipse;
static Toolkit tools = Toolkit.getDefaultToolkit();
static int screenWidth = (int)(Math.round(tools.getScreenSize().getWidth()));
static int screenHeight = (int)(Math.round(tools.getScreenSize().getHeight()));
private static Rectangle paddleRect;
JLabel text = new JLabel("cool");
Timer timeMove = new Timer(1, this);
Timer timeBall = new Timer(10, new timeBall());
private static double x = screenWidth/2, y = (screenHeight*0.8), xx = 0, yy = 0, score = 0, Ox = screenWidth/2, Oy = screenHeight/2, Oyy = 0, width = 100, height = 30;
public nonaMaingamePractice(){
setLayout(new BorderLayout());
timeBall.start();
timeMove.start();
addKeyListener(this);
setFocusable(true);
JPanel panelNorth = makePanel();
panelNorth.setBackground(Color.CYAN);
add(panelNorth, BorderLayout.NORTH);
JLabel scoreLabel = new JLabel("Score: " + score);
panelNorth.add(scoreLabel);
}
public void paintComponent(Graphics g){
super.paintComponent(g);
g.setColor(Color.BLUE);
paddleRect = new Rectangle((int)x, (int)y, (int)width, (int)height);
ellipse = new Ellipse2D.Double(Ox, Oy+Oyy, 50, 50);
Graphics2D graphics = (Graphics2D)g;
graphics.fill(paddleRect);
graphics.fill(ellipse);
}
#Override
public void actionPerformed(ActionEvent e) {
x = x + xx;
y = y + yy;
if(x<0){
x=0;
xx=0;
}
repaint();
}
#Override
public void keyTyped(KeyEvent e) {
// TODO Auto-generated method stub
}
#Override
public void keyPressed(KeyEvent e) {
int c = e.getKeyCode();
if(c==KeyEvent.VK_RIGHT){
xx=1;
}else if(c==KeyEvent.VK_LEFT){
xx=-1;
}
}
#Override
public void keyReleased(KeyEvent e) {
xx=0;
}
protected JPanel makePanel() {
#SuppressWarnings("serial")
JPanel pane = new JPanel() {
#Override
public Dimension getPreferredSize() {
return new Dimension(100, 30);
}
};
pane.setBackground(Color.CYAN);
return pane;
}
protected class timeBall implements ActionListener{
Timer timeWhateva = new Timer(100, this);
#Override
public void actionPerformed(ActionEvent e) {
try{
System.out.println(paddleRect.getX());
if(ellipse.intersects(paddleRect)){
timeWhateva.start();
Oy+=-1;
System.out.println(ellipse.getX() + " " + ellipse.getY());
}else if(!ellipse.intersects(paddleRect)){
Oyy+=1;
}
}catch(RuntimeException NullPointerException){
System.out.println(NullPointerException.getMessage());
}
repaint();
}
}
public static void main(String[] args){
nonaMaingamePractice main = new nonaMaingamePractice();
JFrame frame = new JFrame();
frame.add(main);
frame.setVisible(true);
frame.setTitle("Project 4 game");
frame.setSize(screenWidth, screenHeight);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
Okay, so there seems to a few things that are wrong.
First, don't rely on static for cross object communication, this is a really bad idea which will come back to bite you hard. Instead, pass information to the classes which need it.
Second, I'd focus on having a single Timer (or "main-loop") which is responsible for updating the current state of the game and scheduling repaints. This is the basic concept of Model-View-Controller paradigm
The first thing I'm going to do is take your code apart completely and rebuild it...
To start with, I want some kind of interface which provides information about the current state of the game and which I can pass instances of to other parts of the game in order for them to make decisions and update the state of the game...
public interface GameView {
public boolean isKeyRightPressed();
public boolean isKeyLeftPressed();
public Dimension getSize();
public void updateState();
}
This provides information about the state of the right and left keys, the size of the view and provides some basic functionality to request that the view update it's current state
Next, we need some way to model the state of the game...
import java.awt.Rectangle;
import java.awt.geom.Ellipse2D;
public interface GameModel {
public Rectangle getPaddle();
public Ellipse2D getBall();
public void ballWasMissed();
}
So, this basically maintains information about the paddle and ball and provides a means by which the "main game loop" can provide notification about the state of the game back to the model
Next, we need to the actual "main game loop" or controller. This is responsible for updating the state of the model and updating the view...
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Ellipse2D;
public class MainLoop implements ActionListener {
private GameView gameView;
private GameModel gameModel;
private int ballYDelta = 1;
public MainLoop(GameView gameView, GameModel gameModel) {
this.gameView = gameView;
this.gameModel = gameModel;
}
#Override
public void actionPerformed(ActionEvent e) {
Rectangle paddle = gameModel.getPaddle();
Ellipse2D ball = gameModel.getBall();
// Update the paddle position...
if (gameView.isKeyLeftPressed()) {
paddle.x--;
} else if (gameView.isKeyRightPressed()) {
paddle.x++;
}
// Correct for overflow...
if (paddle.x < 0) {
paddle.x = 0;
} else if (paddle.x + paddle.width > gameView.getSize().width) {
paddle.x = gameView.getSize().width - paddle.width;
}
// Update the ball position...
Rectangle bounds = ball.getBounds();
bounds.y += ballYDelta;
if (bounds.y < 0) {
bounds.y = 0;
ballYDelta *= -1;
} else if (bounds.y > gameView.getSize().height) {
// Ball is out of bounds...
// Notify the gameView so it knows what to do when the ball goes
// out of the game view's viewable, ie update the score...
// Reset ball position to just out side the top of the view...
gameModel.ballWasMissed();
bounds.y = -bounds.height;
} else if (paddle.intersects(bounds)) {
// Put the ball to the top of the paddle
bounds.y = paddle.y - bounds.height;
// Bounce
ballYDelta *= -1;
}
ball.setFrame(bounds);
// Update the view
gameView.updateState();
}
}
This is basically where we are making decisions about the current position of the objects and updating their positions. Here we check for "out-of-bounds" positions and update their states appropriately (for example, the ball can "bounce" and change directions)
The delta values are quite small, so you might want to play around with those
And finally, we need something that pulls it all together...
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.Timer;
public class NonaMaingamePractice extends JPanel implements KeyListener, GameView {
/**
*
*/
private static final long serialVersionUID = 1L;
JLabel text = new JLabel("cool");
private Timer timeBall;
private GameModel model;
private boolean init = false;
private boolean rightIsPressed;
private boolean leftIsPressed;
public NonaMaingamePractice() {
setLayout(new BorderLayout());
addKeyListener(this);
setFocusable(true);
JPanel panelNorth = makePanel();
panelNorth.setBackground(Color.CYAN);
add(panelNorth, BorderLayout.NORTH);
JLabel scoreLabel = new JLabel("Score: " + 0);
panelNorth.add(scoreLabel);
addComponentListener(new ComponentAdapter() {
#Override
public void componentResized(ComponentEvent e) {
if (getWidth() > 0 && getHeight() > 0 && !init) {
init = true;
model = new DefaultGameModel(getSize());
timeBall = new Timer(40, new MainLoop(NonaMaingamePractice.this, model));
timeBall.start();
} else if (model != null) {
model.getPaddle().y = (getHeight() - model.getPaddle().height) - 10;
}
}
});
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.BLUE);
Graphics2D graphics = (Graphics2D) g;
if (model != null) {
graphics.fill(model.getPaddle());
graphics.fill(model.getBall());
}
}
#Override
public void keyTyped(KeyEvent e) {
// TODO Auto-generated method stub
}
#Override
public void keyPressed(KeyEvent e) {
int c = e.getKeyCode();
if (c == KeyEvent.VK_RIGHT) {
rightIsPressed = true;
} else if (c == KeyEvent.VK_LEFT) {
leftIsPressed = true;
}
}
#Override
public void keyReleased(KeyEvent e) {
int c = e.getKeyCode();
if (c == KeyEvent.VK_RIGHT) {
rightIsPressed = false;
} else if (c == KeyEvent.VK_LEFT) {
leftIsPressed = false;
}
}
protected JPanel makePanel() {
#SuppressWarnings("serial")
JPanel pane = new JPanel() {
#Override
public Dimension getPreferredSize() {
return new Dimension(100, 30);
}
};
pane.setBackground(Color.CYAN);
return pane;
}
#Override
public boolean isKeyRightPressed() {
return rightIsPressed;
}
#Override
public boolean isKeyLeftPressed() {
return leftIsPressed;
}
#Override
public void updateState() {
// Maybe update the score??
repaint();
}
public static void main(String[] args) {
NonaMaingamePractice main = new NonaMaingamePractice();
JFrame frame = new JFrame();
frame.add(main);
frame.setVisible(true);
frame.setTitle("Project 4 game");
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
So I have to move my (multiple) images across a GUI, but for whatever reason my paint method is only being called twice, even though my x variable and my timer, which I am using to try and move the image, are incrementing correctly. Any help would be appriciated! Thanks
import javax.swing.*;
import java.awt.*;
import java.lang.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.Random;
public class Races extends JFrame
{
public int threadCount = 5;
public int x = 0;
public ImageIcon picture = new ImageIcon("races.jpeg");
public int height = picture.getIconHeight();
public int width = picture.getIconHeight();
public Races(int _threadCount)
{
threadCount = _threadCount;
int counter = 0;
while(counter<threadCount)
{
(new Thread(new RacesInner(threadCount))).start();
counter++;
}
initialize();
}
public static void main(String[] args)
{
if(args.length == 0)
{
JFrame f = new Races(5);
}
else
{
JFrame f = new Races(Integer.parseInt(args[0]));
}
}
public void initialize()
{
this.setVisible(true);
this.setTitle("Off to the Races - By ");
RacesInner inner = new RacesInner(threadCount);
this.add(inner);
this.setSize((width*20),(height*3)*threadCount);
this.setLocationRelativeTo(null);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.repaint();
}
protected class RacesInner extends JPanel implements Runnable
{
public int j = (int)(Math.random() * 50) + 20;
public void timer()
{
Timer timer1 = new Timer(j, new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
x += 2;
repaint();
}
});
timer1.start();
}
public void run()
{
timer();
}
#Override
public void paint(Graphics g)
{
super.paintComponent(g);
//drawing the correct amount of icons based on input(or lack of input, default 5)
//Get the current size of this component
Dimension d = this.getSize();
//draw in black
g.setColor(Color.BLACK);
//calculating where finish line should be and drawing the line
int finishLine;
finishLine = (width*20)-(width*2);
g.drawLine(finishLine,0,finishLine,2000);
for(int i =0; i<threadCount; i++)
{
picture.paintIcon(this,g,1+x,(50*i));
}
}
public RacesInner(int _threadCount)
{
threadCount = _threadCount;
System.out.println(threadCount);
//JPanel
this.setVisible(true);
this.setLayout(new GridLayout(threadCount,1));
}
}//closes RacesInner class
}//closes races class