Related
My game is similar to Packman. My problem is, that if Packman will eat the point, no one disappear respectively every point except the first one will change colour like background. I know a I have it in method, but It did what I want when I draw just one point. I just want to clear the point which Packman ate. I created the window in WindowBuilder (I just wanted to try it), I hope it won't be a problem.
public class Hra extends JFrame {
private JPanel contentPane;
PackMan packman ;
Points point ;
boolean check;
ArrayList<Body> points = new ArrayList<Body>();
static int x =900;
static int y=600;
Color packCol = Color.BLACK;
Color pointCol = Color.WHITE;
/**
* Launch the application.
*/
public static void main(String[] args) {
Game frame = new Game();
frame.setVisible(true);
}
public void inicialization() {
for (int i = 0; i < 4; i++) {
Point point = new Point(x, y, 20, pointCol);
x +=100;
points.add(point);
}
}
public GAME() {
inicialization();
packman = new PackMan(0, 900, 900,packCol);
point = new point(900,800,20,pointCol);
check = false;
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 450, 300);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
setContentPane(contentPane);
getContentPane().setBackground(Color.YELLOW);
JLabel lblNewLabel = new JLabel("Score:" + packman.getScore());
GroupLayout gl_contentPane = new GroupLayout(contentPane);
gl_contentPane.setHorizontalGroup(
gl_contentPane.createParallelGroup(Alignment.LEADING)
.addGroup(gl_contentPane.createSequentialGroup()
.addContainerGap()
.addComponent(lblNewLabel, GroupLayout.PREFERRED_SIZE, 107, GroupLayout.PREFERRED_SIZE)
.addContainerGap(309, Short.MAX_VALUE))
);
gl_contentPane.setVerticalGroup(
gl_contentPane.createParallelGroup(Alignment.LEADING)
.addGroup(gl_contentPane.createSequentialGroup()
.addComponent(lblNewLabel, GroupLayout.PREFERRED_SIZE, 24, GroupLayout.PREFERRED_SIZE)
.addContainerGap(229, Short.MAX_VALUE))
);
contentPane.setLayout(gl_contentPane);
this.addKeyListener(new KeyListener() {
#Override
public void keyTyped(KeyEvent e) {
// TODO Auto-generated method stub
}
#Override
public void keyReleased(KeyEvent e) {
// TODO Auto-generated method stub
switch(e.getKeyCode()) {
case 37: //left
packman.setCoordinatesX(packman.getCoordinatesX()-10);
repaint();
chechCollision();
break;
case 38: //up
packman.setCoordinatesY(packman.getCoordinatesY()-10);
repaint();
chechCollision();
break;
case 39://right
packman.setCoordinatesX(packman.getCoordinatesX()+10);
repaint();
chechCollision();
break;
case 40://down
packman.setCoordinatesY(packman.getCoordinatesY()+10);
chechCollision();
repaint();
break;
}
}
#Override
public void keyPressed(KeyEvent e) {
// TODO Auto-generated method stub
}
});
}
#Override
public void paint(Graphics g) {
// TODO Auto-generated method stub
super.paint(g);
g.fillRect(packman.getCoordinatesX(), packman.getCoordinatesY(), 50, 50);
g.setColor(point.getColor());
g.fillRect(point.getPointX(), body.getPointY(), 50, 50);
g.setColor(Color.BLACK);
for(int i =0;i<points.size();i++){
if (kontrola) {
g.clearRect(points.get(i).getPointX(), points.get(i).getPointY(), 50, 50);
}
}
for (int i = 0; i < bodiky.size(); i++) {
g.fillRect(points.get(i).getPointX(), points.get(i).getPointY(), 50, 50);
g.setColor(points.get(i).getColor());
}
}
}
public void checkCollision() {
if (packman.getCoordinatesX() == point.getPointX() && packman.getCoordinatesY() == point.getPointY()) {
packman.setScore(packman.getScore() + point.getValueOfPoint());
lblNewLabel.setText("Score:" + packman.getScore() );
check = true;
point.setColor(Color.YELLOW);
point.setValueOfPoint(0);
repaint();
}
}
}
}
public class Point{
private Color color;
private int pointX;
private int pointY;
private double valueofPoint;
public int getCoordinatesPointX() {
return pointX;
}
public Point(int pointX, int pointY, double valueofPoint,Color color) {
super();
this.pointX = pointX;
this.pointY = pointY;
this.valueofPoint= valueofPoint;
this.color = color;
}
public void sePointX(int pointX) {
this.pointX = pointX;
}
public int getPointY() {
return pointY;
}
public void setPointY(int pointY) {
this.pointY = pointY;
}
public double getValueofPoint() {
return valueofPoint;
}
public void setValueofPoint(double valueofPoint) {
this.valueofPoint = valueofPoint;
}
public void setColor(Color color){
this.color = color;
}
public Color getColor(){
return color;
}
}
public class PackMan {
private double score;
private int coordinatesX;
private int coordinatesY;
public double getScore() {
return score;
}
public void setScore(double score) {
this.score = score;
}
public int getCoordinatesX() {
return coordinatesX;
}
public void setCoordinatesX(int coordinatesX) {
this.coordinatesX = coordinatesX;
}
public int getCoordinatesY() {
return coordinatesY;
}
public void setCoordinatesY(int coordinatesY) {
this.coordinatesY = coordinatesY;
}
public PackMan(double score, int coordinatesX, int coordinatesY) {
super();
this.score = score;
this.coordinatesX = coordinatesX;
this.coordinatesY = coordinatesY;
}
}
Packman(for now just black Rectangle) is trying to eat the the first point(this point is firs in List too),but ,,dissapear"(Point has just changed the colour like background) the second one
[2 picture] result and problem which I described in 1
Pakcman has moved to another point with same result offcourse
I just want to eat the point just like in Packman
public void checkCollision() {
if (packman.getCoordinatesX() == point.getPointX() && packman.getCoordinatesY() == point.getPointY()) {
packman.setScore(packman.getScore() + point.getValueOfPoint());
lblNewLabel.setText("Score:" + packman.getScore() );
check = true;
point.setColor(Color.YELLOW);
point.setValueOfPoint(0);
repaint();
points.remove(i);
}
pacman after what changed direction
public class Hra extends JFrame {
Timer timer;
private JPanel contentPane;
PackMan packman ;
Points point ;
boolean check;
ArrayList<Point> points = new ArrayList<Point>();
static int x =900;
static int y=600;
Color packCol = Color.BLACK;
Color pointCol = Color.WHITE;
static Direction vysledek = new Direction(null);
static int newX = 900;
static int newY =200;
static int xVel = 1;
static int yVel = 1;
static int count = 1;
static JLabel gifLabel = new JLabel(new ImageIcon(//path of Image));
/**
* Launch the application.
*/
public static void main(String[] args) {
Game frame = new Game();
frame.setVisible(true);
frame.getContentPane().add(gifLabel);
gifLabel.setLocation(packman.getCoordinatesX(),packman.getCoordinatesY()-38);
}
public void inicialization() {
for (int i = 0; i < 4; i++) {
Point point = new Point(x, y, 20, pointCol);
y -=100;
points.add(point);
}
for (int i = 0; i < 4; i++) {
Point p = new Point(newX, newY, 20, pointCol);
newX-=100;
points.add(p);
}
}
public GAME() {
inicialization();
packman = new PackMan(0, 900, 900,packCol);
point = new point(900,800,20,pointCol);
check = false;
timer = new Timer(10,this);
timer.start();
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 450, 300);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
setContentPane(contentPane);
getContentPane().setBackground(Color.YELLOW);
JLabel lblNewLabel = new JLabel("Score:" + packman.getScore());
GroupLayout gl_contentPane = new GroupLayout(contentPane);
gl_contentPane.setHorizontalGroup(
gl_contentPane.createParallelGroup(Alignment.LEADING)
.addGroup(gl_contentPane.createSequentialGroup()
.addContainerGap()
.addComponent(lblNewLabel, GroupLayout.PREFERRED_SIZE, 107, GroupLayout.PREFERRED_SIZE)
.addContainerGap(309, Short.MAX_VALUE))
);
gl_contentPane.setVerticalGroup(
gl_contentPane.createParallelGroup(Alignment.LEADING)
.addGroup(gl_contentPane.createSequentialGroup()
.addComponent(lblNewLabel, GroupLayout.PREFERRED_SIZE, 24, GroupLayout.PREFERRED_SIZE)
.addContainerGap(229, Short.MAX_VALUE))
);
contentPane.setLayout(gl_contentPane);
this.addKeyListener(new KeyListener() {
#Override
public void keyTyped(KeyEvent e) {
// TODO Auto-generated method stub
}
#Override
public void keyReleased(KeyEvent e) {
// TODO Auto-generated method stub
switch(e.getKeyCode()) {
case 37: //left
count = 1;
repaint();
chechCollision();
break;
case 38: //up
count =2;
repaint();
chechCollision();
break;
case 39://right
count = 3;
repaint();
chechCollision();
break;
case 40://down
count = 4;
chechCollision();
repaint();
break;
}
}
#Override
public void keyPressed(KeyEvent e) {
// TODO Auto-generated method stub
}
});
}
#Override
public void paint(Graphics g) {
// TODO Auto-generated method stub
super.paint(g);
g.fillRect(packman.getCoordinatesX(), packman.getCoordinatesY(), 50, 50);
g.setColor(point.getColor());
for (int i = 0; i < points.size(); i++) {
g.drawOval(points.get(i).getPointX(), points.get(i).getPointY(), 50, 50);
g.fillOval(points.get(i).getPointX(), points.get(i).getPointY(), 50, 50);
}
}
}
public void checkCollision() {
if (packman.getCoordinatesX() == point.getPointX() && packman.getCoordinatesY() == point.getPointY()) {
packman.setScore(packman.getScore() + point.getValueOfPoint());
lblNewLabel.setText("Score:" + packman.getScore() );
points(i);
repaint();
}
}
}
#Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
if (count == 1) {
packman.setCoordinatesX(packman.getCoordinates() - xVel);
gifLabel.setLocation(packman.getCoordinatesX(), packman.getCoordinatesY()-38);
repaint();
chechCollision();
}
if (count ==2) {
packman.setCoordinatesY(packman.getCoordinatesY() - yVel);
gifLabel.setLocation(packman.getCoordinatesX(), packman.getCoordinatesY()-38);
repaint();
chechCollision();
}
if (count ==3) {
packman.setCoordinatesX(packman.getSouradniceX() + xRychlost);
gifLabel.setLocation(packman.getSouradniceX(), packman.getSouradniceY()-38);
repaint();
chechCollision();
}
if (count ==4) {
packman.setCoordinatesY(packman.getCoordinatesY() + yVel);
gifLabel.setLocation(packman.getSouradniceX(), packman.getCoordinatesY()-38);
repaint();
chechCollision();
}
}
public class Direction {
private Directions directions;
private int index;
public Smery getDirection() {
return directions;
}
public void setSmery(Directions directions) {
this.directions = directions;
}
public directions(Directions directions) {
super();
this.directions = directions;
}
public enum Smery {
doprava,doleva,nahoru,dolu;
}
Introduction
I could not get your code to compile.
Here's my best guess as to what your GUI looks like when it starts up.
Here's what the GUI looks like after I've eaten a pellet.
Here's what the GUI looks like after I've eaten more pellets.
Explanation
Do not use static variables.
Do not use so many global variables. You created a model, so pass the model to the controller classes.
Why did you make the score variable a double? An int seems like it would work.
Model
You had the right idea. You created a Packman class to hold a packman and a Point class to hold a pellet. I renamed your Point class to Pellet because there's a java.awt.Point class that is useful for this code.
I saved the center point of the packman and the center point of each pellet. You'll see in the drawing code how I adjust the center point to draw an oval.
I created a GameModel class to hold a java.util.List of Pellet instances, and a Packman instance. The code to check for collisions is also included in this class.
The collision detection is simple. If the center of the pellet and the center of the packman are close enough together, then the packman eats the pellet.
View
I started the Swing application with a call to the SwingUtilities invokeLater method. This method ensures that the Swing components are created and executed on the Event Dispatch Thread.
I created a JFrame, a score JPanel, and a drawing JPanel. I didn't extend a JFrame. I used a JFrame. I don't care how large the JFrame is, so I used the pack method to pack the components on the JFrame.
The score JPanel uses a FlowLayout to place the JLabel and JTextField in the JPanel.
The drawing JPanel extends JPanel so I can override the paintComponent method. It's much easier to draw on a drawing JPanel. You don't have to take the rest of the GUI into account. All the drawing Panel does is draw the packman and the pellets. Moving the packman and checking for collisions happen in the controller classes.
I used KeyBindings rather than a KeyListener. Generally, key bindings are more reliable than a key listener. It's too easy for the component to lose focus and for the keys to stop working. Sure, the key bindings code looks scary at first glance. I have to look up the format every time I want to use them, which is why I provided the link. But in the long run key bindings are better.
I coded indirect key actions. The key presses just change the Direction enum in the Packman class. The java.swing.Timer ActionListener actually moves the packman. This makes the motion much smoother.
If you want to make the packman move faster or slower, adjust the distance parameter in the Packman move method.
For some reason I can't determine, the left and right arrow keys don't respond. I coded the WSAD keys as a substitute. I know the code works because it works with the WSAD keys. If I ever figure out why the left and right arrow keys are unresponsive, I'll update this answer.
Controller
I have a NavigationAction class to listen for the key bindings and a MotionListener class to move the packman.
The NavigationAction class indirectly updates the Direction enum in the Packman class.
The MotionListener class moves the packman and checks for collisions. Since these methods are in other classes, the actionPerformed method is short and easy to understand.
Code
Here's the complete, formatted, runnable code. I made all the classes inner classes so I could post the code as one large block.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import java.util.List;
import javax.swing.AbstractAction;
import javax.swing.ActionMap;
import javax.swing.BorderFactory;
import javax.swing.InputMap;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
public class PackmanGUI implements Runnable {
public static void main(String[] args) {
SwingUtilities.invokeLater(new PackmanGUI());
}
private DrawingPanel drawingPanel;
private final GameModel model;
private JFrame frame;
private JPanel scorePanel;
private JTextField scoreField;
private Timer timer;
public PackmanGUI() {
this.model = new GameModel();
}
#Override
public void run() {
frame = new JFrame("Packman");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
scorePanel = createScorePanel();
frame.add(scorePanel, BorderLayout.BEFORE_FIRST_LINE);
drawingPanel = new DrawingPanel(model);
frame.add(drawingPanel, BorderLayout.CENTER);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
setKeyBindings();
timer = new Timer(40, new MotionListener(this, model));
timer.start();
}
private void setKeyBindings() {
String up = "up";
String down = "down";
String left = "left";
String right = "right";
String pressed = " pressed";
String released = " released";
InputMap inputMap = drawingPanel.getInputMap(JPanel.WHEN_IN_FOCUSED_WINDOW);
ActionMap actionMap = drawingPanel.getActionMap();
inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_W, 0, false), up + pressed);
inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_S, 0, false), down + pressed);
inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_A, 0, false), left + pressed);
inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_D, 0, false), right + pressed);
inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_W, 0, true), up + released);
inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_S, 0, true), down + released);
inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_A, 0, true), left + released);
inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_D, 0, true), right + released);
inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0, false), up + pressed);
inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0, false), down + pressed);
inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0, false), left + pressed);
inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0, false), right + pressed);
inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0, true), up + released);
inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0, true), down + released);
inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0, true), left + released);
inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0, true), right + released);
Packman packman = model.getPackman();
actionMap.put(up + pressed, new NavigationAction(Direction.UP, packman));
actionMap.put(down + pressed, new NavigationAction(Direction.DOWN, packman));
actionMap.put(left + pressed, new NavigationAction(Direction.LEFT, packman));
actionMap.put(right + pressed, new NavigationAction(Direction.RIGHT, packman));
actionMap.put(up + released, new NavigationAction(Direction.NONE, packman));
actionMap.put(down + released, new NavigationAction(Direction.NONE, packman));
actionMap.put(left + released, new NavigationAction(Direction.NONE, packman));
actionMap.put(right + released, new NavigationAction(Direction.NONE, packman));
}
private JPanel createScorePanel() {
JPanel panel = new JPanel(new FlowLayout());
panel.setBackground(Color.YELLOW);
panel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
Font font = panel.getFont().deriveFont(Font.BOLD, 36f);
JLabel label = new JLabel("Score:");
label.setFont(font);
panel.add(label);
scoreField = new JTextField(10);
scoreField.setBackground(Color.YELLOW);
scoreField.setEditable(false);
scoreField.setFont(font);
scoreField.setHorizontalAlignment(JTextField.TRAILING);
updateScore(model.getPackman().getScore());
panel.add(scoreField);
return panel;
}
public void updateScore(double score) {
scoreField.setText(Double.toString(score));
}
public JFrame getFrame() {
return frame;
}
public void repaint() {
drawingPanel.repaint();
}
public class DrawingPanel extends JPanel {
private static final long serialVersionUID = 1L;
private final GameModel model;
public DrawingPanel(GameModel model) {
this.model = model;
this.setBackground(Color.BLACK);
this.setPreferredSize(new Dimension(800, 800));
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Packman packman = model.getPackman();
Point point = packman.getCenterPoint();
// Draw body
int x = point.x - 25;
int y = point.y - 25;
g.setColor(Color.YELLOW);
g.fillArc(x, y, 50, 50, 30, 300);
// Draw eye
x = point.x;
y = point.y - 18;
g.setColor(Color.BLACK);
g.fillOval(x, y, 8, 8);
// Draw pellets
for (Pellet pellet : model.getPellets()) {
g.setColor(pellet.getColor());
point = pellet.getPoint();
x = point.x - 10;
y = point.y - 10;
g.fillOval(x, y, 20, 20);
}
}
}
public interface KeyDirectionActionHandler {
public void keyDirectionActionPerformed(Direction direction);
}
public class NavigationAction extends AbstractAction {
private static final long serialVersionUID = 1L;
private Direction direction;
private KeyDirectionActionHandler keyDirectionActionHandler;
public NavigationAction(Direction direction,
KeyDirectionActionHandler keyDirectionActionHandler) {
this.direction = direction;
this.keyDirectionActionHandler = keyDirectionActionHandler;
}
#Override
public void actionPerformed(ActionEvent event) {
keyDirectionActionHandler.keyDirectionActionPerformed(direction);
}
}
public enum Direction {
NONE, UP, DOWN, RIGHT, LEFT;
}
public class MotionListener implements ActionListener {
private final PackmanGUI frame;
private final GameModel model;
public MotionListener(PackmanGUI frame, GameModel model) {
this.frame = frame;
this.model = model;
}
#Override
public void actionPerformed(ActionEvent event) {
model.getPackman().move();
model.checkCollisions();
frame.updateScore(model.getPackman().getScore());
frame.repaint();
}
}
public class GameModel {
private final List<Pellet> pellets;
private final Packman packman;
public GameModel() {
this.packman = new Packman(0, new Point(400, 400));
this.pellets = new ArrayList<>();
inicialization();
}
public void inicialization() {
int x = 600;
int y = 600;
for (int i = 0; i < 4; i++) {
Pellet pellet = new Pellet(new Point(x, y), 20, Color.WHITE);
y -= 100;
pellets.add(pellet);
}
for (int i = 0; i < 4; i++) {
Pellet pellet = new Pellet(new Point(x, y), 20, Color.WHITE);
x -= 100;
pellets.add(pellet);
}
}
public void checkCollisions() {
Point packmanPoint = packman.getCenterPoint();
for (int index = 0; index < pellets.size(); index++) {
Pellet pellet = pellets.get(index);
Point pelletPoint = pellet.getPoint();
// Collision detection
int deltaX = packmanPoint.x - pelletPoint.x;
int deltaY = packmanPoint.y - pelletPoint.y;
double distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
if (distance < 20) {
pellets.remove(pellet);
packman.incrementScore(pellet.getValue());
}
}
}
public List<Pellet> getPellets() {
return pellets;
}
public Packman getPackman() {
return packman;
}
}
public class Packman implements KeyDirectionActionHandler {
private double score;
private Direction direction;
private Point centerPoint;
public Packman(double score, Point centerPoint) {
this.score = score;
this.centerPoint = centerPoint;
this.direction = Direction.NONE;
}
public double getScore() {
return score;
}
public void incrementScore(double score) {
this.score += score;
}
public Point getCenterPoint() {
return centerPoint;
}
public void setCenterPoint(Point centerPoint) {
this.centerPoint = centerPoint;
}
public void move() {
int distance = 6;
int deltaX = 0;
int deltaY = 0;
switch (direction) {
case NONE:
deltaX = 0;
deltaY = 0;
break;
case UP:
deltaX = 0;
deltaY = -distance;
break;
case DOWN:
deltaX = 0;
deltaY = distance;
break;
case LEFT:
deltaX = -distance;
deltaY = 0;
break;
case RIGHT:
deltaX = distance;
deltaY = 0;
}
int x = centerPoint.x + deltaX;
int y = centerPoint.y + deltaY;
this.centerPoint = new Point(x, y);
}
#Override
public void keyDirectionActionPerformed(Direction direction) {
this.direction = direction;
}
}
public class Pellet {
private double value;
private Color color;
private Point point;
public Pellet(Point point, double value, Color color) {
this.point = point;
this.value = value;
this.color = color;
}
public double getValue() {
return value;
}
public void setValue(double value) {
this.value = value;
}
public Color getColor() {
return color;
}
public void setColor(Color color) {
this.color = color;
}
public Point getPoint() {
return point;
}
public void setPoint(Point point) {
this.point = point;
}
}
}
I am following a the following video to design a snake game:
https://www.youtube.com/watch?v=91a7ceECNTc
I am following it step by step, but when I run it, the snake does not show on my screen, just the apple. I think I have something wrong when implementing public void paint(Graphics g); Can someone help me?
This is the code my Main class
import javax.swing.JFrame;
public class Main {
public static void main(String[] args) {
JFrame frame = new JFrame ();
GamePanel panel = new GamePanel();
frame.add(panel);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setTitle("Snake");
frame.pack();
frame.setVisible(true);
frame.setLocationRelativeTo(null);
}
}
This is the Panel class:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.ArrayList;
import java.util.Random;
import javax.swing.JPanel;
public class GamePanel extends JPanel implements Runnable, KeyListener{
private static final long serialVersionUID = 1L;
public static final int WIDTH = 1000, HEIGHT = 1000; //Dimensions of the panel (Will be set by user input later)
private Thread thread;
private boolean running;
private boolean right = true, left = false, up = false, down = false;
private BodyPart b;
private ArrayList<BodyPart> snake;
private Apple apple;
private ArrayList<Apple> apples;
private Random r;
private int xCoor = 100, yCoor = 100, size = 10;
private int ticks = 0;
public GamePanel() {
setFocusable(true);
setPreferredSize(new Dimension(WIDTH, HEIGHT));
addKeyListener(this);
snake = new ArrayList<BodyPart>();
apples = new ArrayList<Apple>();
r = new Random();
start();
}
public void start() {
running = true;
thread = new Thread(this);
thread.start();
}
public void stop() {
running = false;
try {
thread.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void tick() {
if (snake.size() == 0) {
b = new BodyPart(xCoor, yCoor, 10);
snake.add(b);
}
ticks++;
if (ticks > 250000) {
if (right) {
xCoor++;
}
if (left) {
xCoor--;
}
if (up) {
yCoor--;
}
if (down) {
yCoor++;
}
ticks = 0;
b = new BodyPart(xCoor, yCoor, 10);
snake.add(b);
if (snake.size() > size) {
snake.remove(0);
}
}
if (apples.size() == 0) {
int xCoor = r.nextInt(99);
int yCoor = r.nextInt(99);
apple = new Apple(xCoor, yCoor, 10);
apples.add(apple);
}
}
public void paint(Graphics g) {
g.clearRect(0, 0, WIDTH, HEIGHT);
g.setColor(Color.BLACK);
g.fillRect(0, 0, WIDTH, HEIGHT);
for (int i = 0; i < WIDTH/10; i++) {
g.drawLine(i*10, 0, i*10, HEIGHT);
}
for (int i = 0; i < HEIGHT/10; i++) {
g.drawLine(0, i*10, HEIGHT, i*10);
}
for (int i = 0; i < snake.size(); i++) {
snake.get(i).draw(g);
}
for (int i = 0; i < apples.size(); i++) {
apples.get(i).draw(g);
}
}
#Override
public void run() {
while (running) {
tick();
repaint();
}
}
#Override
public void keyTyped(KeyEvent e) {
int key = e.getKeyCode();
if (key == KeyEvent.VK_RIGHT && !left) {
right = true;
up = false;
down = false;
}
if (key == KeyEvent.VK_LEFT && !right) {
left = 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;
}
}
#Override
public void keyPressed(KeyEvent e) {
// TODO Auto-generated method stub
}
#Override
public void keyReleased(KeyEvent e) {
// TODO Auto-generated method stub
}
}
The Snake's body parts class:
import java.awt.Color;
import java.awt.Graphics;
public class BodyPart {
public int xCoor, yCoor, width, height;
public BodyPart(int xCoor, int yCoor, int tileSize) {
this.xCoor = xCoor;
this.yCoor = yCoor;
width = tileSize;
height = tileSize;
}
public void tick() {
}
public void draw(Graphics g) {
g.setColor(Color.YELLOW);
g.fillRect(xCoor * width, yCoor * height, width, height);
}
public int getCoorX() {
return xCoor;
}
public void setCoorX (int xCoor) {
this.xCoor = xCoor;
}
public int getCoorY() {
return yCoor;
}
public void setCoorY(int yCoor) {
this.yCoor = yCoor;
}
}
And the Apple's Class:
import java.awt.Color;
import java.awt.Graphics;
public class Apple {
public int xCoor, yCoor, width, height;
public Apple(int xCoor, int yCoor, int tileSize) {
this.xCoor = xCoor;
this.yCoor = yCoor;
width = tileSize;
height = tileSize;
}
public void tick() {
}
public void draw(Graphics g) {
g.setColor(Color.RED);
g.fillRect(xCoor * width, yCoor * height, width, height);
}
public int getxCoor() {
return xCoor;
}
public void setxCoor(int xCoor) {
this.xCoor = xCoor;
}
public int getyCoor() {
return yCoor;
}
public void setyCoor(int yCoor) {
this.yCoor = yCoor;
}
}
Okay, so the issue comes down to some basic maths...
If we take a look at the draw method for BodyPart you will find...
g.fillRect(xCoor * width, yCoor * height, width, height);
Okay, pretty basic, but are all these values actually set too?
If we take a look at the tick method (where BodyParts are created), we can find...
b = new BodyPart(xCoor, yCoor, 10);
snake.add(b);
Okay, so the width and height is 10, but what about xCoor and yCoor?
They're first initialised as instance fields along with the class...
private int xCoor = 100, yCoor = 100, size = 10;
So, a quick bit of maths tells us the initial location of the BodyPart is 100 * 10 which equals 1000x1000.
If we also take a look at ...
public static final int WIDTH = 1000, HEIGHT = 1000; //Dimensions of the panel (Will be set by user input later)
and
setPreferredSize(new Dimension(WIDTH, HEIGHT));
we can see that the BodyPart is actually been set off screen initially.
So, if we change the initial position to something more like...
private int xCoor = 10, yCoor = 10, size = 10;
you will find your missing snake.
General advice...
You should avoid overriding paint. It's to high in the paint chain and it's to easy to screw it up. Instead, prefer paintComponent instead (and make sure you're calling super.paintComponent). JPanel will then clear the Graphics context for you (with the background color of the component).
Swing is not thread safe. You should not be modify the UI or any state the UI relies on from outside the context of the Event Dispatching Thread.
The current "main" loop is in danger of introducing dirty updates which could cause issues later. See Concurrency in Swing. As a "general" preference, you should consider using a Swing Timer instead. It won't block the EDT, but's "ticks" are generated inside the EDT, making it safer to update the UI and/or its state from within.
You should avoid using "magic numbers" when performing your operations...
for (int i = 0; i < WIDTH/10; i++) {
g.drawLine(i*10, 0, i*10, HEIGHT);
}
Here, WIDTH and HEIGHT may not represent that actual size of the component. Instead make use of JPanel#getWidth and JPanel#getHeight instead.
As a general recommendation, you should avoid using setPreferred/Minimum/MaximumSize, it's to easy for someone else to change these to a state you don't want. Instead, override getPreferred/Minimum/MaximumSize instead, this way you maintain control.
So, I had a problem concerning a Try Again button that would show on Game Over screen and when clicked on reset everything to initial value. Now that problem is partially solved but every time I click on it everything becomes crazy fast and with each click faster and faster.
Here is my code from class which does initialization:
public class game extends JPanel implements ActionListener{
private static final long serialVersionUID = 1L;
private Menu menu;
private GameOver gameover;
//variables
public static int cyclesToWait = 50;
public static int enemiesKilled = 0;
public static int life = 3;
int roundCount = 0;
Timer gamelooptimer;
//objects
Player p;
ControllerEnemy c;
ControllerRocket r;
ControllerExplosion e;
//is it new round or not --> for enemy control
public static enum ROUND{
INPROGRESS,
NEW
}
public static enum STATE{
MENU,
GAME,
OVER
};
public static STATE State = STATE.MENU;
public static ROUND Round = ROUND.INPROGRESS;
public game(){
setFocusable(true);
initGame();
}
public void resetGame(){
initGame();
}
private void initGame(){
enemiesKilled = 0;
life = 3;
roundCount = 0;
gamelooptimer = new Timer(10, this);
gamelooptimer.start();
p = new Player(MainClass.width / 2 - 60, 400);
c = new ControllerEnemy();
r = new ControllerRocket();
e = new ControllerExplosion();
menu = new Menu();
gameover = new GameOver();
addKeyListener(new KeyInput(p));
addMouseListener(new MouseInput());
}
public void paint(Graphics g){
super.paint(g);
Graphics2D g2d = (Graphics2D) g;
g2d.drawImage(getBackgroundImage(), 0, 0, null);
Font fnt = new Font("arial", Font.BOLD, 22);
g.setFont(fnt);
if(State == STATE.GAME){
p.draw(g2d);
c.draw(g2d);
r.draw(g2d);
e.draw(g2d);
g.drawString("Round: " + roundCount, MainClass.width - 125, 22);
g.drawString("Enemies Killed: " + enemiesKilled, MainClass.width/2 - 95, 22);
if(cyclesToWait < 50)
cyclesToWait++;
}
else if (State == STATE.OVER)
gameover.render(g);
else
menu.render(g);
}
#Override
public void actionPerformed(ActionEvent e) {
repaint();
if(State == STATE.GAME){
p.update();
c.update();
r.update();
}
if(Round == ROUND.NEW)
roundCount += 1;
}
private Image getBackgroundImage(){
ImageIcon i = new ImageIcon(getClass().getResource("/images/Background.png"));
return i.getImage();
}
resetGame() is called from another class.
I'm trying to code a simple Pong and I have the background panel which contains a Bar panel. So of course I need to be able to place the bar on the size and move it vertically at request. Now I'm just trying to put it in a starting position. If I don't disable the layout the bar gets placed in the top center regardless of location setting, but if I disable the layout and set location it just doesn't show up. I'm not sure what I missing. Here is a code snippet if it can be relevant:
public PongPanel() {
setLayout(null);
setPreferredSize(SIZE);
setBackground(Color.BLACK);
player_one_bar = new Bar();
add(player_one_bar);
player_one_bar.setLocation(10, getSize().height/2-3);
}
If you set the layout manager as null you'll have to specify the exact coordinates of the panel, meaning something like -
setBounds(10, 10, 20, 100);
Will put the panel at location (10,10) with Width of 20 and Height of 100.
If by "bar" you mean Pong game paddle, then it shouldn't be a component at all but rather a logical entity that represents a position, which is visually represented by a sprite that gets drawn in the JPanel's paintComponent method.
For example:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
public class PongPaddle extends JPanel {
private static final int PREF_W = 800;
private static final int PREF_H = 500;
private static final int RECT_X = 20;
private static final int RECT_W = 10;
private static final int RECT_H = 60;
private static final int STARTING_Y = (PREF_H - RECT_H) / 2;
private static final int TIMER_DELAY = 15;
private static final int DELTA_PADDLE = 3;
private boolean paddle1GoingDown = true;
private boolean paddle2GoingDown = false;
private Rectangle paddle1 = new Rectangle(RECT_X, STARTING_Y, RECT_W, RECT_H);
private Rectangle paddle2 = new Rectangle(PREF_W - RECT_X - RECT_W,
STARTING_Y, RECT_W, RECT_H);
public PongPaddle() {
setBackground(Color.black);
new Timer(TIMER_DELAY, new TimerListener()).start();
}
#Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(PREF_W, PREF_H);
}
private class TimerListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
int deltaPaddle1 = paddle1GoingDown ? 1 : -1;
deltaPaddle1 *= DELTA_PADDLE;
int x = paddle1.getLocation().x;
int y = paddle1.getLocation().y + deltaPaddle1;
if (y + RECT_H >= PREF_H) {
paddle1GoingDown = false;
}
if (y <= 0) {
paddle1GoingDown = true;
}
paddle1.setLocation(x, y);
int deltaPaddle2 = paddle2GoingDown ? 1 : -1;
deltaPaddle2 *= DELTA_PADDLE;
x = paddle2.getLocation().x;
y = paddle2.getLocation().y + deltaPaddle2;
if (y + RECT_H >= PREF_H) {
paddle2GoingDown = false;
}
if (y <= 0) {
paddle2GoingDown = true;
}
paddle2.setLocation(x, y);
repaint();
if (!PongPaddle.this.isShowing()) {
((Timer) e.getSource()).stop();
}
}
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setColor(Color.white);
if (paddle1 != null) {
g2.fill(paddle1);
}
if (paddle2 != null) {
g2.fill(paddle2);
}
}
private static void createAndShowGui() {
PongPaddle mainPanel = new PongPaddle();
JFrame frame = new JFrame("PongPaddle");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
I have displayed an image(ball) inside the JApplet, now I want the image to move in a vertical way (up and down). The problem is I don't know how to do it.
Could someone has an idea about this matter?
You need to set the position of that image to some calculated value (means you caculate the vertical position using time, speed and maybe other restrictions).
How you'd set that position depends on how you draw the image.
Example, based on drawing in the applet's (or a nested component's) paint(Graphics g) method:
//first calculate the y-position
int yPos += timeSinceLastPaint * speed; //increment the position
if( (speed > 0 && yPos > someMaxY) || (speed < 0 && yPos <0 ) ) {
speed *= -1; //if the position has reached the bottom (max y) or the top invert the direction
}
//in your paint(Graphics g) method:
g.drawImage(image, yPos, x, null);
Then you'd have to constantly repaint the applet.
More information on animations in applets can be found here: http://download.oracle.com/javase/tutorial/uiswing/components/applet.html
another example for javax.swing.Timer with moving Ojbects created by paintComponent(Graphics g), and I have lots of Start, not some blurred Mikado :-)
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
import javax.swing.Timer;
public class AnimationBackground {
private Random random = new Random();
private JFrame frame = new JFrame("Animation Background");
private final MyJPanel panel = new MyJPanel();
private JLabel label = new JLabel("This is a Starry background.", JLabel.CENTER);
private JPanel stopPanel = new JPanel();
private JPanel startPanel = new JPanel();
public AnimationBackground() {
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setResizable(false);
panel.setBackground(Color.BLACK);
for (int i = 0; i < 50; i++) {
Star star = new Star(new Point(random.nextInt(490), random.nextInt(490)));
star.setColor(new Color(100 + random.nextInt(155), 100 + random.nextInt(155), 100 + random.nextInt(155)));
star.setxIncr(-3 + random.nextInt(7));
star.setyIncr(-3 + random.nextInt(7));
panel.add(star);
}
panel.setLayout(new GridLayout(10, 1));
label.setForeground(Color.WHITE);
panel.add(label);
stopPanel.setOpaque(false);
stopPanel.add(new JButton(new AbstractAction("Stop this madness!!") {
private static final long serialVersionUID = 1L;
#Override
public void actionPerformed(ActionEvent e) {
panel.stopAnimation();
}
}));
panel.add(stopPanel);
startPanel.setOpaque(false);
startPanel.add(new JButton(new AbstractAction("Start moving...") {
private static final long serialVersionUID = 1L;
#Override
public void actionPerformed(ActionEvent e) {
panel.startAnimation();
}
}));
panel.add(startPanel);
frame.add(panel);
frame.pack();
frame.setLocation(150, 150);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
AnimationBackground aBg = new AnimationBackground();
}
});
}
private class Star extends Polygon {
private static final long serialVersionUID = 1L;
private Point location = null;
private Color color = Color.YELLOW;
private int xIncr, yIncr;
static final int WIDTH = 500, HEIGHT = 500;
Star(Point location) {
int x = location.x;
int y = location.y;
this.location = location;
this.addPoint(x, y + 8);
this.addPoint(x + 8, y + 8);
this.addPoint(x + 11, y);
this.addPoint(x + 14, y + 8);
this.addPoint(x + 22, y + 8);
this.addPoint(x + 17, y + 12);
this.addPoint(x + 21, y + 20);
this.addPoint(x + 11, y + 14);
this.addPoint(x + 3, y + 20);
this.addPoint(x + 6, y + 12);
}
public void setColor(Color color) {
this.color = color;
}
public void move() {
if (location.x < 0 || location.x > WIDTH) {
xIncr = -xIncr;
}
if (location.y < 0 || location.y > WIDTH) {
yIncr = -yIncr;
}
translate(xIncr, yIncr);
location.setLocation(location.x + xIncr, location.y + yIncr);
}
public void setxIncr(int xIncr) {
this.xIncr = xIncr;
}
public void setyIncr(int yIncr) {
this.yIncr = yIncr;
}
public Color getColor() {
return color;
}
}
private class MyJPanel extends JPanel {
private static final long serialVersionUID = 1L;
private ArrayList<Star> stars = new ArrayList<Star>();
private Timer timer = new Timer(20, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
for (Star star : stars) {
star.move();
}
repaint();
}
});
public void stopAnimation() {
if (timer.isRunning()) {
timer.stop();
}
}
public void startAnimation() {
if (!timer.isRunning()) {
timer.start();
}
}
#Override
public void addNotify() {
super.addNotify();
timer.start();
}
#Override
public void removeNotify() {
super.removeNotify();
timer.stop();
}
MyJPanel() {
this.setPreferredSize(new Dimension(512, 512));
}
public void add(Star star) {
stars.add(star);
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
((Graphics2D) g).setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
for (Star star : stars) {
g.setColor(star.getColor());
g.fillPolygon(star);
}
}
}
}
How to move the image inside the JApplet ..?
Pretty much exactly the same way you might do it in a JFrame, JComponent or JPanel or...
Or to put that another way, nothing to do with applets and everything to do with Graphics2D. For more details, see the 2D Graphics Trail of the Java Tutorial.
When you've figured how to move an image and paint it to a Graphics2D, implement that logic in a JComponent or JPanel's paintComponent(Graphics) method and drop the component with moving image into a JApplet or JFrame (or a JPanel etc.).
For the animation side of it, use a javax.swing.Timer as seen in this example. This example does not extend any component. Instead, it creates a BufferedImage and adds it to a JLabel that is displayed to the user. When the timer fires, the code grabs the Graphics object of the image, and proceeds from there to draw the bouncing lines.
import java.awt.image.BufferedImage;
import java.awt.event.*;
import java.awt.geom.*;
import java.awt.*;
import javax.swing.*;
import java.util.Random;
class LineAnimator {
public static void main(String[] args) {
final int w = 640;
final int h = 480;
final RenderingHints hints = new RenderingHints(
RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON
);
hints.put(
RenderingHints.KEY_ALPHA_INTERPOLATION,
RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY
);
final BufferedImage bi = new BufferedImage(w,h, BufferedImage.TYPE_INT_ARGB);
final JLabel l = new JLabel(new ImageIcon(bi));
final BouncingLine[] lines = new BouncingLine[100];
int factor = 1;
for (int ii=0; ii<lines.length; ii++) {
lines[ii] = new BouncingLine(w*factor,h*factor);
}
final Font font = new Font("Arial", Font.BOLD, 30);
ActionListener al = new ActionListener() {
int count = 0;
long lastTime;
String fps = "";
private final BasicStroke stroke = new BasicStroke(6);
public void actionPerformed(ActionEvent ae) {
count++;
Graphics2D g = bi.createGraphics();
g.setRenderingHints(hints);
g.setColor(new Color(55,12,59));
g.fillRect(0,0,w,h);
g.setStroke(stroke);
for (int ii=0; ii<lines.length; ii++) {
lines[ii].move();
lines[ii].paint(g);
}
if ( System.currentTimeMillis()-lastTime>1000 ) {
lastTime = System.currentTimeMillis();
fps = count + " FPS";
count = 0;
}
g.setColor(Color.YELLOW);
g.setFont(font);
g.drawString(fps,5,h-5);
l.repaint();
g.dispose();
}
};
Timer timer = new Timer(25,al);
timer.start();
JOptionPane.showMessageDialog(null, l);
//System.exit(0);
timer.stop();
}
}
class BouncingLine {
private final Color color;
private static final Random random = new Random();
Line2D line;
int w;
int h;
int x1;
int y1;
int x2;
int y2;
BouncingLine(int w, int h) {
line = new Line2D.Double(random.nextInt(w),random.nextInt(h),random.nextInt(w),random.nextInt(h));
this.w = w;
this.h = h;
this.color = new Color(
random.nextInt(255)
,random.nextInt(255)
,random.nextInt(255)
,64+random.nextInt(128)
);
x1 = (random.nextBoolean() ? 1 : -1);
y1 = (random.nextBoolean() ? 1 : -1);
x2 = -x1;
y2 = -y1;
}
public void move() {
int tx1 = 0;
if (line.getX1()+x1>0 && line.getX1()+x1<w) {
tx1 = (int)line.getX1()+x1;
} else {
x1 = -x1;
tx1 = (int)line.getX1()+x1;
}
int ty1 = 0;
if (line.getY1()+y1>0 && line.getY1()+y1<h) {
ty1 = (int)line.getY1()+y1;
} else {
y1 = -y1;
ty1 = (int)line.getY1()+y1;
}
int tx2 = 0;
if (line.getX2()+x2>0 && line.getX2()+x2<w) {
tx2 = (int)line.getX2()+x2;
} else {
x2 = -x2;
tx2 = (int)line.getX2()+x2;
}
int ty2 = 0;
if (line.getY2()+y2>0 && line.getY2()+y2<h) {
ty2 = (int)line.getY2()+y2;
} else {
y2 = -y2;
ty2 = (int)line.getY2()+y2;
}
line.setLine(tx1,ty1,tx2,ty2);
}
public void paint(Graphics g) {
Graphics2D g2 = (Graphics2D)g;
g2.setColor(color);
//line.set
g2.draw(line);
}
}
Update 1
I want to do it in JApplet(1) using the image(2), is it possible(3)?
The examples by mKorbel and myself feature either an image in a JLabel or custom rendering in a JPanel. In our case, we added the components to a JOptionPane & a JFrame. Either example could be just as easily added to a JApplet, or a JDialog, or as part of another panel, or.. See the Laying Out Components Within a Container lesson & Using Top-Level Containers in the Java Tutorial for more details.
Instead of the stars or lines in our examples, ..paint your image. My example goes so far as to demonstrate how to get the position to bounce around within the bounds of the container.
Sure it is possible, but "Batteries not included". Our intention is to give you some ideas that you can then adapt to your bouncing ball applet. I doubt anyone is going to create an example for you, using balls, in an applet. Though if you post an SSCCE that shows your intent and what you tried, I (and others) would often run with that source. If you want more specific answers, ask a more specific SSCCE. ;)
I want to do it in JApplet.
Why not both? You can have a hybrid application/applet as shown in this animation.