I am trying to make a Sprite move across a background image in swing, but every time I update the position and it repaints, it repaints with the previous position of the image as well. However I am just trying to make it so that it moves 10 pixels for every time the right arrow is pressed. Here is the Main class, which controls the movement.
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.*;
public class Main extends JFrame implements KeyListener, ActionListener{
private static final long serialVersionUID = 1L;
//Caitlan info
Image caitlanImage = new ImageIcon("Caitlan.png").getImage();
Person caitlan = new Person(caitlanImage, "Caitlan", 50, 200, true);
//Jake info
Image jakeImage = new ImageIcon("Jake.png").getImage();
Person jake = new Person(jakeImage, "Jake", 0, 200, true);
//Level objects
Image granadaBackground = new ImageIcon("Granada Background.jpg").getImage();
Level granada = new Level(granadaBackground, "Granada", new Point(600, 300));
Image elevatorBackground = new ImageIcon("Elevator.png").getImage();
Level elevator = new Level(elevatorBackground, "Elevator", new Point(0,0));
public static void main(String[] args) throws InterruptedException{
new Main();
}
public Main() throws InterruptedException{ //Constructor (only should be called once)
setSize(700,300);
setTitle("Project Anniversary");
setVisible(true);
setDefaultCloseOperation(EXIT_ON_CLOSE);
addKeyListener(this);
}
public void paint(Graphics g){ //Overridden paint method.
if(checkIfLevelDone(granada, caitlan)){
granada.setDone();
}
if(!granada.isDone()){
g.drawImage(granada.getImage(), 0, 0, granadaBackground.getWidth(null), granadaBackground.getHeight(null),null);
g.drawImage(jake.getImage(), jake.getPosX(), jake.getPosY(), jake.getImage().getWidth(null), jake.getImage().getHeight(null),null);
g.drawImage(caitlan.getImage(), caitlan.getPosX(), caitlan.getPosY(), caitlan.getImage().getWidth(null), caitlan.getImage().getHeight(null), null);
}
else if(granada.isDone()){
setSize(300,300);
g.drawImage(elevator.getImage(), 0, 0,
elevator.getImage().getWidth(null), elevator.getImage().getHeight(null),null);
g.drawImage(jake.getImage(), jake.getPosX(), jake.getPosY(),
jake.getImage().getWidth(null), jake.getImage().getHeight(null),null);
g.drawImage(caitlan.getImage(), caitlan.getPosX(), caitlan.getPosY(),
caitlan.getImage().getWidth(null), caitlan.getImage().getHeight(null), null);
}
}
public void keyPressed(KeyEvent e) { //Method called whenever a key is pressed
caitlan.printLocation();
int code = e.getKeyCode();
if(code == KeyEvent.VK_RIGHT){ //When the user presses the right arrow
caitlan.setLocation(caitlan.getPosX() + 10, caitlan.getPosY());
repaint();
}
if(code == KeyEvent.VK_LEFT){ //When the user presses the left arrow
caitlan.setLocation(caitlan.getPosX() - 10, caitlan.getPosY());
repaint();
}
if(code == KeyEvent.VK_UP){ //Implement jumping code here
repaint();
}
}
public boolean checkIfLevelDone(Level l, Person p){
//Method to check if a given level is done
if(l.getCompletionPoint().x <= p.getPosX()){
return true;
}
return false;
}
public void followOtherPerson(Person a, Person b) throws InterruptedException{
//Method to follow the other character
}
public void jump(Person p) throws InterruptedException{ //Jump method
caitlan.setLocation(caitlan.getPosX(), caitlan.getPosY() - 60);
repaint();
}
public void keyReleased(KeyEvent e) { //IGNORE
}
public void keyTyped(KeyEvent e) { //IGNORE
}
public void actionPerformed(ActionEvent e) { //IGNORE
}
}
Here is the Level class:
import java.awt.Image;
import java.awt.Point;
public class Level {
//Private attributes
private Image backgroundImage; //Image
private String levelName; //Name of level
private boolean levelComplete; //Status that holds if the level is done
private Point completionPoint; //Point at which the level is completed
public Level(Image i, String l, Point p){ //Constructor
this.backgroundImage = i;
this.levelName = l;
this.completionPoint = p;
levelComplete = false;
}
public void setDone(){
levelComplete = true;
}
public boolean isDone(){ //Returns if the level is done or not
return levelComplete;
}
public Image getImage(){ //Getters and setters
return backgroundImage;
}
public String getLevelName(){
return levelName;
}
public void setImage(Image i){
this.backgroundImage = i;
}
public void setName(String name){
this.levelName = name;
}
public Point getCompletionPoint(){
return completionPoint;
}
public void setCompletionPoint(Point p){
this.completionPoint = p;
}
}
And finally, here is the Person class.
import java.awt.*;
public class Person{
//Attributes
private Image image;
private String name;
private int xlocation;
private int ylocation;
/*Boolean that you can publically access to determine if the given Person object is a
player*/
public boolean isPlayer;
public Person(Image i, String s){ //Really shouldn't be used
this.image = i;
this.name = s;
}
public Person(Image i){ //Really shouldn't be used
this.image = i;
}
public Person(Image i, String s, int xloc, int yloc){ //Basic constructor
this.name = s;
this.image = i;
this.xlocation = xloc;
this.ylocation = yloc;
}
public Person(Image i, String s, int xloc, int yloc, boolean isPlayer){ //Detailed constructor
this.name = s;
this.image = i;
this.xlocation = xloc;
this.ylocation = yloc;
this.isPlayer = isPlayer;
}
public void printLocation(){
System.out.println("Person " + name + " is at location (" + xlocation +", " + ylocation +").");
}
public void incrementPositionX(){ //Increase xlocation by 1
xlocation++;
}
public void incrementPositionY(){ //Increase ylocation by 1
ylocation++;
}
public void setName(String name){ //Method to change the name of a sprite
this.name = name;
}
public void setImage(Image image){ //Method to change the image of a sprite
this.image = image;
}
public Image getImage(){ //Get image
return image;
}
public int getPosX(){ //Get x position
return xlocation;
}
public int getPosY(){ //Get y position
return ylocation;
}
public String getName(){ //Get name
return name;
}
public void setLocation(int x, int y){ //Method to change the location of a sprite
this.xlocation = x;
this.ylocation = y;
}
}
You should not paint directly on top level container such as JFrame. Instead, use JComponent or JPanel. Override paintComponent() for painting rather than paint() and don't forget to call super.paintComponent(g)
Take a look at Performing Custom Painting tutorial for more information.
Also, key listener is a lower level interface. It is best to use Key Bindings instead. See How to Use Key Bindings for details and examples.
Also, there is no need to create ImageIcon to get Image. Look into ImageIO.read() methods.
Related
I just wrote some code to make my player move in my little maze game, but nothing happens. Also my maze is not drawn correct as in the matrix input. I don't figure out why is wrong this code...any help is well appeciated.
Thank you!
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
import javax.swing.*;
public class Main extends JPanel {
private static Image white;
private static Image black;
private static Image finish;
private static Image player;
private static int x = 1;
private static int y = 1;
private String matrix[][];
public Main() {
addKeyListener(new Keys());
setFocusable(true);
}
public static String[][] load(String input) {
List<String[]> rows = new ArrayList<>();
try (Scanner scanner = new Scanner(input)) {
while (scanner.hasNextLine()) {
String line = scanner.nextLine();
String[] cols = new String[line.length()];
for (int i = 0; i < cols.length; i++) {
cols[i] = line.substring(i, i + 1);
}
rows.add(cols);
}
}
return rows.toArray(new String[rows.size()][]);
}
public static JFrame buildFrame() {
JFrame frame = new JFrame("Labyrinth Game");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(900, 950);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
return frame;
}
public void moveUp() {
x += 0;
y += -1;
}
public void moveLeft() {
x += -1;
y += 0;
}
public void moveDown() {
x += 0;
y += 1;
}
public void moveRight() {
x += 1;
y += 0;
}
public class Keys extends KeyAdapter {
#Override
public void keyPressed(KeyEvent e) {
int keycode = e.getKeyCode();
// repaint();
if (keycode == KeyEvent.VK_W) {
if (!matrix[getX()][getY() - 1].equals("1")) {
moveUp();
}
}
if (keycode == KeyEvent.VK_A) {
if (!matrix[getX() - 1][getY()].equals("1")) {
moveLeft();
}
}
if (keycode == KeyEvent.VK_S) {
if (!matrix[getX()][getY() + 1].equals("1")) {
moveDown();
}
}
if (keycode == KeyEvent.VK_D) {
if (!matrix[getX() + 1][getY()].equals("1")) {
moveRight();
}
}
}
#Override
public void keyReleased(KeyEvent event) {
}
}
public static void main(String[] args) {
String input = "1111111111111111111111111111111111111111111\n"
+ "1000000010001000001000000010000000100000001\n"
+ "1010111010101010101111101011111010111111101\n"
+ "1010001010100010100000001010000010000010001\n"
+ "1011101010111110101111111010111111111010111\n"
+ "1000101010100000101000001000100010000010001\n"
+ "1011101011101011111011101111111010111110101\n"
+ "1010001000001010000010100000001010000010101\n"
+ "1010111111111010111110111111101011111011101\n"
+ "1010100000100010100000000000101000000000101\n"
+ "1110101111101110111110111011101011111110101\n"
+ "1000100000000010000010100010001000100010001\n"
+ "1011111111111111111011101010111111101011101\n"
+ "1000000000000000100010001010000000001010001\n"
+ "1011111111111011101110111011111111111010111\n"
+ "1000100010001000001010001000100000001010101\n"
+ "1110101011101111111010101110111110111010101\n"
+ "1000101010001000100000101000100000100010001\n"
+ "1011101010111010101111101011101110101111111\n"
+ "1000001010000010000000101000001000100010001\n"
+ "1111111011111110111111101111111011111010101\n"
+ "1000001010000010100010001000000010000010101\n"
+ "1011111010111011101010111011111110101110101\n"
+ "1010000010001010001010001000100000101010101\n"
+ "1010111111101010111011101111101111101011101\n"
+ "1000100000001010101010001000100010101000101\n"
+ "1011111011111010101010111010111010101011101\n"
+ "1010000010001000101010000010001010001000001\n"
+ "1010101110101111101011101111101011111010101\n"
+ "1010101000101000001000101000001000000010101\n"
+ "1011101011111010111110111011101111111110111\n"
+ "1000001000000010000000000010000000000010021\n"
+ "1111111111111111111111111111111111111111111\n";
String[][] matrix = load(input);
JFrame frame = buildFrame();
ImageIcon img = new ImageIcon("C:/Users/Desktop/black20.png");
black = img.getImage();
img = new ImageIcon("C:/Users/Desktop/gri20.png");
white = img.getImage();
img = new ImageIcon("C:/Users/Desktop/finish20.png");
finish = img.getImage();
img = new ImageIcon("C:/Users/Desktop/smiley20.png");
player = img.getImage();
// frame.add(new Player());
JPanel pane = new JPanel() {
#Override
public void paint(Graphics g) {
super.paint(g);
for (int i = 0; i < matrix.length; i++) {
for (int j = 0; j < matrix[0].length; j++) {
if (matrix[i][j].equals("1")) {
g.drawImage(black, i * 20, j * 20, null);
}
if (matrix[i][j].equals("0")) {
g.drawImage(white, i * 20, j * 20, null);
}
if (matrix[i][j].equals("2")) {
g.drawImage(finish, i * 20, j * 20, null);
}
}
}
g.drawImage(player, x * 20, y * 20, null);
}
};
frame.add(pane);
frame.add(new Main());
}
}
It should look like:
Problems/Suggestions:
You're adding more than one component to the JFrame in a default fashion. Since the JFrame's contentPane uses BorderLayout, only one component will display, the last one added, and the other will be completely covered and will remain invisible.
Your Main JPanel is not being used as a true JPanel. Nothing is being added to it, and in fact it looks like it should be a logical class and not a component class.
Rather than using KeyListeners, which are very fidgety when it comes to focus problems, use Key Bindings which will allow you to get around focus issues in a clean and higher level way.
Don't override the JPanel's paint method but rather its paintComponent method as this will give you several advantages, including default use of double buffering for your animation.
Don't give component classes a public int getX() and public int getY() method without care since these override key methods that place the component within its container. Since the Main class shouldn't even extend JPanel, this will end up to be a non-issue for your code, but in the future, it would mess your program up.
When you run into similar problems, such as a KeyListener not working, remove the issue from your big program and try to reproduce it in a small separate program. This will give you a much cleaner environment for helping you to isolate and understand your problem and thereby help you fix it.
Your program is mis-using the static modifier. Your x and y fields should not be static and should not be accessed in a static way.
You've got way too much code within your main method, which is one of the reasons why you likely made x and y static, because you were forced to do so since you're trying to access them within main. The solution is not to make the fields static but to get all that code out of the static world and into the instance world.
Edit
For some reason the question intrigued me, and so I decided to try to M-V-C or Model-View-Controller it if possible and see what I could come up with. So here goes a bunch of classes that sort of work, beginning with a text file that holds the data.
The GUI looks like:
It must be in the same location as the class files since it is obtained as a resource and must have the file name "input.txt"
1111111111111111111111111111111111111111111
1000000010001000001000000010000000100000001
1010111010101010101111101011111010111111101
1010001010100010100000001010000010000010001
1011101010111110101111111010111111111010111
1000101010100000101000001000100010000010001
1011101011101011111011101111111010111110101
1010001000001010000010100000001010000010101
1010111111111010111110111111101011111011101
1010100000100010100000000000101000000000101
1110101111101110111110111011101011111110101
1000100000000010000010100010001000100010001
1011111111111111111011101010111111101011101
1000000000000000100010001010000000001010001
1011111111111011101110111011111111111010111
1000100010001000001010001000100000001010101
1110101011101111111010101110111110111010101
1000101010001000100000101000100000100010001
1011101010111010101111101011101110101111111
1000001010000010000000101000001000100010001
1111111011111110111111101111111011111010101
1000001010000010100010001000000010000010101
1011111010111011101010111011111110101110101
1010000010001010001010001000100000101010101
1010111111101010111011101111101111101011101
1000100000001010101010001000100010101000101
1011111011111010101010111010111010101011101
1010000010001000101010000010001010001000001
1010101110101111101011101111101011111010101
1010101000101000001000101000001000000010101
1011101011111010111110111011101111111110111
1000001000000010000000000010000000000010021
1111111111111111111111111111111111111111111
Next the main program, the one that creates the model, the view, and the controller, hooks them all together, and then displays the GUI:
import java.awt.BorderLayout;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
/**
* link: http://stackoverflow.com/a/41418250/522444
*
* #author Pete
*
*/
#SuppressWarnings("serial")
public class Main2 extends JPanel {
private View mainPanel;
public Main2(MatrixModel matrixModel) {
mainPanel = new View(matrixModel);
new Controller(matrixModel, mainPanel);
setLayout(new BorderLayout());
add(mainPanel, BorderLayout.CENTER);
}
private static void createAndShowGui(MatrixModel model) {
Main2 mainPanel = new Main2(model);
JFrame frame = new JFrame("Main2");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
final MatrixModel model = MatrixUtil.getInput(MatrixUtil.PATH_TO_RSC);
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui(model);
}
});
}
}
Next a utility class with static methods for reading in the text file as a resource and converting it into a Model object:
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
public class MatrixUtil {
// again this text file must be in the jar file or the code base
// at the same location as the class / java files
public static final String PATH_TO_RSC = "input.txt";
public static MatrixModel getInput(String resourcePath) {
InputStream is = MatrixUtil.class.getResourceAsStream(resourcePath);
if (is == null) {
String text = "resourcePath is not found and not loading text: " + resourcePath;
throw new IllegalArgumentException(text);
}
return getInput(is);
}
public static MatrixModel getInput(InputStream is) {
MatrixModel model = null;
try (Scanner scan = new Scanner(is)) {
List<List<MatrixPosition>> listOfLists = new ArrayList<>();
while (scan.hasNextLine()) {
String line = scan.nextLine();
if (line.trim().isEmpty()) {
continue;
}
List<MatrixPosition> list = new ArrayList<>();
for (char c : line.toCharArray()) {
list.add(MatrixPosition.getMatrixPosition(String.valueOf(c)));
}
listOfLists.add(list);
}
MatrixPosition[][] grid = new MatrixPosition[listOfLists.size()][];
for (int i = 0; i < grid.length; i++) {
List<MatrixPosition> list = listOfLists.get(i);
grid[i] = list.toArray(new MatrixPosition[] {});
}
model = new MatrixModel(grid, new SpritePosition(1, 1));
}
return model;
}
}
Basic enum to represent direction:
public enum Direction {
UP, DOWN, LEFT, RIGHT
}
Another enum to represent a location point in the grid, and whether it is a wall, a coridor or the end as well as static methods to convert from number to MatrixPosition:
public enum MatrixPosition {
WALL(1), CORRIDOR(0), END(2);
private int value;
private MatrixPosition(int value) {
this.value = value;
}
public int getValue() {
return value;
}
public static MatrixPosition getMatrixPosition(int value) {
for (MatrixPosition position : MatrixPosition.values()) {
if (value == position.getValue()) {
return position;
}
}
String text = "value of " + value;
throw new IllegalArgumentException(text);
}
public static MatrixPosition getMatrixPosition(String strValue) {
int value = -1;
try {
value = Integer.parseInt(strValue);
} catch (NumberFormatException e) {
String text = "NumberFormatException for strValue " + strValue;
throw new IllegalAccessError(text);
}
return getMatrixPosition(value);
}
}
A class to represent a position of our sprite, similar to the java.awt.Point class but with row and column fields instead of x and y:
public class SpritePosition {
int row;
int column;
public SpritePosition(int row, int column) {
this.row = row;
this.column = column;
}
public int getRow() {
return row;
}
public void setRow(int row) {
this.row = row;
}
public int getColumn() {
return column;
}
public void setColumn(int column) {
this.column = column;
}
public void setRowColumn(int row, int column) {
this.row = row;
this.column = column;
}
}
The model has property change support code so that it can notify any classes listening to it of any changes in its state. The controller will be the class listening to the model
import java.beans.PropertyChangeListener;
import javax.swing.event.SwingPropertyChangeSupport;
public class MatrixModel {
public static final String SPRITE_POINT = "sprite point";
private SwingPropertyChangeSupport pcSupport = new SwingPropertyChangeSupport(this);
private MatrixPosition[][] grid;
private SpritePosition spritePosition;
public MatrixModel(MatrixPosition[][] grid, SpritePosition spritePosition) {
this.grid = grid;
this.spritePosition = spritePosition;
}
public int getRows() {
return grid.length;
}
public int getColumns() {
return grid[0].length;
}
public MatrixPosition getPosition(SpritePosition p) {
return getPosition(p.row, p.column);
}
public MatrixPosition getPosition(int row, int col) {
return grid[row][col];
}
public void setSpritePoint(SpritePosition spritePosition) {
SpritePosition oldValue = this.spritePosition;
SpritePosition newValue = spritePosition;
this.spritePosition = spritePosition;
pcSupport.firePropertyChange(SPRITE_POINT, oldValue, newValue);
}
public boolean isPointValid(SpritePosition p) {
if (p.column < 0 || p.row < 0) {
return false;
}
if (p.column >= grid[0].length || p.row >= grid.length) {
return false;
}
return grid[p.row][p.column] == MatrixPosition.CORRIDOR;
}
public boolean isMoveValid(Direction direction) {
int row = spritePosition.row;
int column = spritePosition.column;
switch (direction) {
case UP:
return isPointValid(new SpritePosition(row - 1, column));
case DOWN:
return isPointValid(new SpritePosition(row + 1, column));
case LEFT:
return isPointValid(new SpritePosition(row, column - 1));
case RIGHT:
return isPointValid(new SpritePosition(row, column + 1));
default:
return false;
}
}
public void move(Direction direction) {
if (!isMoveValid(direction)) {
String text = "For move to " + direction + "spritePosition: " + spritePosition;
throw new IllegalArgumentException(text);
}
int row = spritePosition.row;
int column = spritePosition.column;
switch (direction) {
case UP:
setSpritePoint(new SpritePosition(row - 1, column));
break;
case DOWN:
setSpritePoint(new SpritePosition(row + 1, column));
break;
case LEFT:
setSpritePoint(new SpritePosition(row, column - 1));
break;
case RIGHT:
setSpritePoint(new SpritePosition(row, column + 1));
break;
default:
break;
}
}
public SpritePosition getSpritePosition() {
return spritePosition;
}
public void addPropertyChangeListener(PropertyChangeListener listener) {
pcSupport.addPropertyChangeListener(listener);
}
public void removePropertyChangeListener(PropertyChangeListener listener) {
pcSupport.removePropertyChangeListener(listener);
}
public void addPropertyChangeListener(String name, PropertyChangeListener listener) {
pcSupport.addPropertyChangeListener(name, listener);
}
public void removePropertyChangeListener(String name, PropertyChangeListener listener) {
pcSupport.removePropertyChangeListener(name, listener);
}
}
Controller class, one that sets up key bindings on the view so that it can listen for key presses, checks if they represent a valid move, and if so then tells the model to make the move. It also adds a listener to the model so that when its state changes, it will tell the view to move the sprite
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.EnumMap;
import java.util.Map;
import javax.swing.AbstractAction;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JComponent;
import javax.swing.KeyStroke;
public class Controller {
private MatrixModel model;
private View view;
private Map<Direction, KeyStroke> dirKeyMap = new EnumMap<>(Direction.class);
public Controller(MatrixModel model, View view) {
this.model = model;
this.view = view;
dirKeyMap.put(Direction.DOWN, KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0));
dirKeyMap.put(Direction.UP, KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0));
dirKeyMap.put(Direction.LEFT, KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0));
dirKeyMap.put(Direction.RIGHT, KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0));
model.addPropertyChangeListener(new ModelListener());
setUpKeyBindings(view);
}
private void setUpKeyBindings(View view) {
int condition = JComponent.WHEN_IN_FOCUSED_WINDOW;
InputMap inputMap = view.getInputMap(condition);
ActionMap actionMap = view.getActionMap();
for (Direction dir : Direction.values()) {
KeyStroke keyStroke = dirKeyMap.get(dir);
hookUp(inputMap, actionMap, dir, keyStroke);
}
}
private void hookUp(InputMap inputMap, ActionMap actionMap, Direction dir, KeyStroke key) {
inputMap.put(key, key.toString());
actionMap.put(key.toString(), new MoveAction(dir, model));
}
public MatrixModel getModel() {
return model;
}
public View getView() {
return view;
}
class ModelListener implements PropertyChangeListener {
#Override
public void propertyChange(PropertyChangeEvent evt) {
if (MatrixModel.SPRITE_POINT.equals(evt.getPropertyName())) {
SpritePosition p = model.getSpritePosition();
view.setSpritePoint(p);
}
}
}
}
#SuppressWarnings("serial")
class MoveAction extends AbstractAction {
private Direction dir;
private MatrixModel model;
public MoveAction(Direction dir, MatrixModel model) {
super(dir.toString());
this.dir = dir;
this.model = model;
}
public void actionPerformed(ActionEvent e) {
if (model.isMoveValid(dir)) {
model.move(dir);
}
}
}
Finally the View class, that extends JPanel, that displays the maze and the sprite:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import javax.swing.JPanel;
#SuppressWarnings("serial")
public class View extends JPanel {
private static final int CELL_WIDTH = 20;
private static final Color CORRIDOR_COLOR = Color.LIGHT_GRAY;
private static final Color WALL_COLOR = Color.DARK_GRAY;
private static final Color END_COLOR = Color.ORANGE;
private static final Color SPRITE_COLOR = Color.RED;
private static final int GAP = 1;
private BufferedImage gridImg = null;
private SpritePosition spritePosition;
private JPanel mainPanel = new JPanel();
public View(MatrixModel matrixModel) {
gridImg = createImg(matrixModel);
spritePosition = matrixModel.getSpritePosition();
}
public JPanel getMainPanel() {
return mainPanel;
}
#Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet() || gridImg == null) {
return super.getPreferredSize();
}
int prefW = gridImg.getWidth();
int prefH = gridImg.getHeight();
return new Dimension(prefW, prefH);
}
public void setSpritePoint(SpritePosition spritePosition) {
this.spritePosition = spritePosition;
repaint();
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (gridImg != null) {
g.drawImage(gridImg, 0, 0, this);
}
g.setColor(SPRITE_COLOR);
int y = spritePosition.row * CELL_WIDTH + GAP;
int x = spritePosition.column * CELL_WIDTH + GAP;
g.fillRect(x, y, CELL_WIDTH - 2 * GAP, CELL_WIDTH - 2 * GAP);
}
private BufferedImage createImg(MatrixModel matrixModel) {
BufferedImage img = null;
if (matrixModel != null && matrixModel.getRows() > 0) {
int w = matrixModel.getColumns() * CELL_WIDTH;
int h = matrixModel.getRows() * CELL_WIDTH;
img = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2 = img.createGraphics();
for (int row = 0; row < matrixModel.getRows(); row++) {
for (int col = 0; col < matrixModel.getColumns(); col++) {
MatrixPosition position = matrixModel.getPosition(row, col);
Color c = null;
switch (position) {
case CORRIDOR:
c = CORRIDOR_COLOR;
break;
case WALL:
c = WALL_COLOR;
break;
case END:
c = END_COLOR;
break;
}
g2.setColor(c);
int x = col * CELL_WIDTH;
int y = row * CELL_WIDTH;
g2.fillRect(x, y, CELL_WIDTH, CELL_WIDTH);
}
}
g2.dispose();
}
return img;
}
}
This my code for the simple maze game. Its being compiled and class file of MazeGame.java and Board.java are being created but not of Player.java and Map.java. The code is being compiled error free but its not running. Please help me out.
//MazeGame.java
package mygame;
import javax.swing.*;
public class MazeGame {
public static void main(String[] args) {
new MazeGame();
}
public MazeGame() {
JFrame f= new JFrame();
f.setTitle("Maze Game");
f.setSize(450,450);
f.setLocationRelativeTo(null);
f.add(new Board());
f.setVisible(true);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
//Board.java
package mygame;
import java.awt.event.*;
import javax.swing.*;
import java.awt.*;
import java.awt.*;
public class Board extends JPanel implements ActionListener {
private Timer timer;
private Map m;
private Player p;
private boolean win=false;
private String Message="";
private Font font = new Font("Comic Sans",Font.BOLD,50);
public Board() {
m = new Map();
p = new Player();
addKeyListener(new Al());
setFocusable(true);
timer = new Timer(25,this);
timer.start();
}
public void paint(Graphics g)
{
super.paint(g);
if(!win)
{
for(int y=0; y<14; y++) {
for(int x=0; x<14; x++) {
if(m.getMap(x,y).equals("f")) {
g.drawImage(m.getFinish(),x*32,y*32,null);
}
if(m.getMap(x,y).equals("g")) {
g.drawImage(m.getGrass(),x*32,y*32,null);
}
if(m.getMap(x,y).equals("w")) {
g.drawImage(m.getWall(),x*32,y*32,null);
}
}
}
g.drawImage(p.getPlayer(),p.getTileX()*32,p.getTileY()*32,null);
}
if(win)
{
g.setColor(Color.BLUE);
g.setFont(font);
g.drawString(Message,100,300);
}
}
public class Al extends KeyAdapter {
public void keyPressed(KeyEvent e) {
int keyCode = e.getKeyCode();
if((keyCode==KeyEvent.VK_W) || (keyCode==KeyEvent.VK_UP)) {
if(!(m.getMap(p.getTileX(),p.getTileY()-1).equals("w"))) {
p.move(0,-1);
}
}
if((keyCode==KeyEvent.VK_S) || (keyCode==KeyEvent.VK_DOWN)) {
if(!(m.getMap(p.getTileX(),p.getTileY()+1).equals("w"))) {
p.move(0,1);
}
}
if((keyCode==KeyEvent.VK_A) || (keyCode==KeyEvent.VK_LEFT)) {
if(!(m.getMap(p.getTileX(),p.getTileY()-1).equals("w"))) {
p.move(-1,0);
}
}
if((keyCode==KeyEvent.VK_D) || (keyCode==KeyEvent.VK_RIGHT)) {
if(!(m.getMap(p.getTileX(),p.getTileY()-1).equals("w"))) {
p.move(1,0);
}
}
}
}
public void actionPerformed(ActionEvent e) {
if(m.getMap(p.getTileX(),p.getTileY()).equals("f")) {
Message = "WINNER!!!";
win = true;
}
repaint();
}
}
//Map.java
package mygame;
import java.util.*;
import java.io.*;
import java.awt.*;
import java.awt.*;
public class Map {
private Scanner s;
private String Map[] = new String[14];
private Image grass,wall,finish;
public Map() {
ImageIcon img = new ImageIcon("G://sonali_java//mygame//grass.png");
grass = img.getImage();
img = new ImageIcon("G://sonali_java//mygame//wall.png");
wall = img.getImage();
img = new ImageIcon("G://sonali_java//mygame//finish.png");
finish = img.getImage();
openFile();
readFile();
closeFile();
}
public String getMap(int x,int y) {
String index = Map[y].substring(x,x+1);
return index;
}
public Image getGrass() {
return grass;
}
public Image getWall() {
return wall;
}
public Image getFinish() {
return finish;
}
public void openFile() {
try {
s= new Scanner(new File("G://sonali_java//mygame//Map.txt"));
}
catch(Exception e) {
System.out.println("Error Loading File!!!!");
}
}
public void readFile() {
while(s.hasNext()) {
for(int i=0; i<14; i++) {
Map[i] = s.next();
}
}
}
public void closeFile() {
s.close();
}
}
//Player.java
package mygame;
import java.awt.*;
public class Player {
private int tileX,tileY;
private Image player;
public Player() {
tileX=1;
tileY=1;
ImageIcon img = new ImageIcon("G://sonali_java//mygane//object.png");
player = img.getImage();
}
public Image getPlayer() {
return player;
}
public int getTileX() {
return tileX;
}
public int getTileY() {
return tileY;
}
public void move(int dx, int dy) {
tileX += dx;
tileY += dy;
}
}
I dont want to be mad but you are defining different folder locations
in some places "G://sonali_java//mygane//object.png", check "mygaNe"
in some places "G://sonali_java//mygame//Map.txt", check "mygaMe"
Are you sure while loading it does not throw a NullPointerException ?
Are you aware that you can, place code like
public void draw(Graphics g){
g.drawImage(playerImg, getX(), getY(), null);
}
in your player class, thus leaving the player class with drawing the player and simply calling the players draw method inside your Board paint method? This can also be done for drawing the map. Remember to call the draw methods in the paint method.
ALSO, THIS
ImageIcon img = new ImageIcon("G://sonali_java//mygane//object.png");
check your directory location
Im working on a program that draws a card from a collection(deck) of uno cards. It should display the first card on startup, then every time the "next card" button is pressed it draws another card. However I'm very new to GUI's and can't figure out what i'm doing wrong. I get "Uno" in the box that should display the text representation of the card.
package Uno;
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
public class GameFrame extends JFrame
{
private PlayingCardPanel panel;
private JPanel field;
private JPanel menu;
public GameFrame(){
this.setLayout(new FlowLayout());
this.setSize( 300, 150);
this.setTitle("UNO");
this.createFieldPanel();
this.createMenuPanel();
this.add(field);
this.add(menu);
}
private void createMenuPanel(){
menu = new JPanel();
menu.setBounds(0,300,250,100);
JButton drawButton = new JButton("Next Card");
drawButton.setSize(300,200);
drawButton.addActionListener(new drawListener());
menu.add(drawButton);
}
private void createFieldPanel()
{
field = new JPanel();
field.setBounds(0,0,250,200);
panel = new PlayingCardPanel();
field.add(panel);
}
private class drawListener implements ActionListener{
public void actionPerformed(ActionEvent e){
panel.drawCard();
}
}
}
package Uno;
import java.awt.*;
import javax.swing.*;
public class PlayingCardPanel extends JPanel{
private StandardDeck playingdeck;
private PlayingCard card;
public PlayingCardPanel(){
this.setPreferredSize(new Dimension(100,100));
playingdeck = new StandardDeck();
playingdeck.shuffle();
playingdeck.drawTopCard();
}
public void drawCard(){
playingdeck.drawTopCard();
}
public void paintComponent(Graphics g){
super.paintComponent(g);
int panelWidth = this.getWidth();
int panelHeight = this.getHeight();
g.drawRoundRect(0, 0, panelWidth-1, panelHeight-1, 10, 10);
card = playingdeck.drawTopCard();
g.drawString(card.toString(), 75, 75);
}
}
package Uno;
import Uno.GameFrame;
public class GameApp{
/**
* #param args
*/
public static void main(String[] args)
{
GameFrame aBoard = new GameFrame();
aBoard.setVisible(true);
}
}
package Uno;
public class PlayingCard {
private int number;
private String color;
public int getNumber() {
return number;
}
public String getColor(){
return color;
}
public PlayingCard(PlayingCard card){
number = card.getNumber();
color = new String(card.getColor());
}
public PlayingCard(int cardNumber, String cardColor){
number = cardNumber;
color = cardColor;
}
}
package Uno;
public class PlayingCard {
private int number;
private String color;
public int getNumber() {
return number;
}
public String getColor(){
return color;
}
public PlayingCard(PlayingCard card){
number = card.getNumber();
color = new String(card.getColor());
}
public PlayingCard(int cardNumber, String cardColor){
number = cardNumber;
color = cardColor;
}
}
package Uno;
import java.util.Collections;
import java.util.Vector;
public class StandardDeck {
protected Vector<PlayingCard> cardsVector;
public StandardDeck(){
cardsVector = new Vector<PlayingCard>();
String[] colors = {"blue","red","yellow","green"};
for(String color : colors){
for(int i=1;i<=9;i++){
cardsVector.add(new PlayingCard(i,color));
cardsVector.add(new PlayingCard(i,color));
}
cardsVector.add(new PlayingCard(0,color));
for(int i=-3;i<0;i++){
cardsVector.add(new PlayingCard(i,color));
cardsVector.add(new PlayingCard(i,color));
}
}
for(int i=0;i<4;i++){
cardsVector.add(new PlayingCard(-4,"black"));
cardsVector.add(new PlayingCard(-5,"black"));
}
}
public int getSize(){
return cardsVector.size();
}
public StandardDeck reset(){
StandardDeck resetDeck = new StandardDeck();
return resetDeck;
}
public void shuffle(){
Collections.shuffle(cardsVector);
}
public PlayingCard drawTopCard(){
return new PlayingCard(cardsVector.remove(cardsVector.size()-1));
}
}
package Uno;
import Uno.IPlayingCard;
public interface IDeck
{
public void reset();
public void shuffle();
public IPlayingCard drawTopCard(PlayingCard card);
}
package Uno;
import Uno.PlayingCard;
public interface IPlayingCard extends Comparable<PlayingCard>{
public String getColor();
public String getNumber();
}
Thanks for any help!
It's actually printing something like Uno.PlayingCard#56609959 -- the last part of it is being truncated though, so you're only seeing "Uno" at the edge of your panel.
You are missing your toString() implementation in PlayingCard class.
public void paintComponent(Graphics g)
{
super.paintComponent(g);
int panelWidth = this.getWidth();
int panelHeight = this.getHeight();
g.drawRoundRect(0, 0, panelWidth - 1, panelHeight - 1, 10, 10);
card = playingdeck.drawTopCard();
g.drawString(card.toString(), 75, 75); // you're calling toString() here...
}
Since you don't have it implemented, it's calling the default Object.toString() method. You probably meant to add something like this to your PlayingCard class?
public String toString() {
return ""+number;
}
I am making a game (see my previous threads) and have encountered a lot of problems on the way. All I know is that he code compiles, runs, but nothing appears in the window, it's just grey. At Andrew Thompson's suggestion, I am posting the entire compilable version here. Sorry for the length but it is ALL the code in the program. And a lot of things will probably not make sense (unused ActionPerformed to name one), partially because I implemented code in the event that I would need it but mostly because I have never done this before.
Also, so far I have no multithreading, because once again, I am new to this, so ideally I would like to keep it that way, if only for the sake of my sanity.
EDIT: Forgot to mention I have 4 PNGs in there representing the 4 different objects that appear. My code is flexible enough for you to supply your own. Here is the image I am using for ships and here is the one for bullets just make copies, put them the source file and name them "Enemy-ship" "ship2" "Ebullet" and "PBullet"
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.Timer;
import javax.swing.JFrame;
public class GameController extends JFrame implements ActionListener {
/**
*
*/
private static final long serialVersionUID = -3599196025204169130L;
private static GameView window;
private static Timer time;
public GameController()
{
setTitle("Space Shooter");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(800, 600);
//window = new GameView(800,600);
//window.setVisible(true);
//
}
//TODO spawn
/*public static void main(String args[])
{
//GameController c = new GameController();
window = new GameView(800,600);
window.setVisible(true);
time = new Timer(40, this);
time.schedule( new TimerTask(){
public void run(){GameState.update();
window.paintComponents(null);}
},0, 40);
}*/
public void display() {
add(new GameView(800,600));
pack();
setMinimumSize(getSize());// enforces the minimum size of both frame and component
setVisible(true);
}
public static void main(String[] args) {
GameController main = new GameController();
main.display();
time = new Timer(40, main);
}
#Override
public void actionPerformed(ActionEvent e) {
if(e instanceof EndEvent)//TODO fix this
{
}
else
{
repaint();
}
}
}
package Game;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
public class GameView extends JComponent implements ActionListener{
/**
*
*/
private static final long serialVersionUID = -2869672245901003704L;
private static final Graphics Graphics = null;
private boolean liveGame;//used so that buttons cannot be clicked after game is complete
private GameState gs;
private Player p;
private int w, h;
public GameView(int width, int height)
{
liveGame = true;
gs = new GameState();
GameState.init(width, height);
p = new Player(width/2,(height*7)/8);
this.setBackground(Color.BLACK);
paintComponents(Graphics);
w = width;
h = height;
}
#Override
public Dimension getMinimumSize() {
return new Dimension(w, h);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(w, h);
}
#Override
public void paintComponent(Graphics g) {
int margin = 10;
Dimension dim = getSize();
super.paintComponent(g);
g.setColor(Color.black);
GameState.update();
for(Bullet j : GameState.getEnBullets()){
g.drawImage(j.getImage(),j.getX(), j.getY(), null);}
for(Enemy j : GameState.getEnemies()){
g.drawImage(j.getImage(),j.getX(), j.getY(), null);}
for(Bullet j : GameState.getPlayBullets()){
g.drawImage(j.getImage(),j.getX(), j.getY(), null);}
g.fillRect(margin, margin, dim.width - margin * 2, dim.height - margin * 2);
}
public void paintComponents (Graphics g)
{
for(Bullet j : GameState.getEnBullets()){
g.drawImage(j.getImage(),j.getX(), j.getY(), null);}
for(Enemy j : GameState.getEnemies()){
g.drawImage(j.getImage(),j.getX(), j.getY(), null);}
for(Bullet j : GameState.getPlayBullets()){
g.drawImage(j.getImage(),j.getX(), j.getY(), null);}
this.paint(g);
}
public void refreshImage()
{
this.removeAll();
paintComponents(Graphics);
}
public void actionPerformed(ActionEvent e) {
}
}
package Game;
import java.awt.event.ActionEvent;
import java.util.ArrayList;
import javax.swing.JFrame;
public class GameState {
private static ArrayList<Bullet> playBullets;
public static ArrayList<Bullet> getPlayBullets() {
return playBullets;
}
public static ArrayList<Bullet> getEnBullets() {
return enBullets;
}
public static ArrayList<Enemy> getEnemies() {
return enemies;
}
public static Player getP() {
return p;
}
private static ArrayList<Bullet> enBullets;
private static ArrayList<Enemy> enemies;
private static int X, Y;//for limit of screen so nothing can go outside of screen
private static Player p;
private static int score;
public GameState(){
}
public static void init(int x, int y)
{
playBullets = new ArrayList<Bullet>();
enBullets = new ArrayList<Bullet>();
enemies = new ArrayList<Enemy>();
X=x;
Y=y;
p = null;
score =0;
}
public static int xLimit(){return X;}
public static int yLimit(){return Y;}
public static int getScore(){return score;}
public static void add (Location e)
{
if(e instanceof Bullet)
{
if(((Bullet) e).getOwner() instanceof Enemy){
enBullets.add((Bullet) e);
}
else
playBullets.add((Bullet) e);
}
else if(e instanceof Enemy){enemies.add((Enemy)e);}
else
p=(Player)e;
}
public static void spawn()
{
Enemy e = new Enemy(((int)(Math.random()*(X-56))+28), 0, 1);
}
public static void playerCD()//detects if player has collided with anything, removes whatever collided with it, and causes the player to take damage
{
if(enemies.size()>0){
for(int i =0; i < enemies.size(); i++)
{
if (p.getLocation().intersects(enemies.get(i).getLocation()))
{
p.takeDamage(enemies.get(i).getDamage());
enemies.get(i).takeDamage(p.getDamage());
}
}
if(enBullets.size()>0)
for(int i =0; i < enBullets.size(); i++)
{
if (p.getLocation().intersects(enBullets.get(i).getLocation()))
{
p.takeDamage(enBullets.get(i).getDamage());
enBullets.remove(i);
i--;
}
}
}
}
public static void enemyCD()
{
for(int i =0; i < enemies.size(); i++)
{
for(int n =0; n < playBullets.size(); n++)
{
if (playBullets.get(n).getLocation().intersects(enemies.get(i).getLocation()))
{
enemies.get(i).takeDamage(playBullets.get(i).getDamage());
playBullets.remove(n);
n--;
score+=50;
}
}
}
}
public static void checkForDead()//clears away dead and things gone offscreen
{
for(int i =0; i < enemies.size(); i++)
{
if(enemies.get(i).getY()>Y)
{
enemies.remove(i);
i--;
}
}
for(int i =0; i < enBullets.size(); i++)
{
if(enBullets.get(i).getY()>Y)
{
enBullets.remove(i);
i--;
}
}
for(int i =0; i < enemies.size(); i++)
{
if(enemies.get(i).getHealth()>0)
{
enemies.remove(i);
i--;
score+=200;
}
}
if(p.getHealth()<=0)
{
ActionEvent e = new EndEvent(null, 0, "end");
}
}
public static void update()
{
move();
playerCD();
enemyCD();
checkForDead();
}
public static void move()
{
p.move();
for(int i =0; i < enemies.size(); i++){enemies.get(i).move();}
for(int i =0; i < enBullets.size(); i++){enBullets.get(i).move();}
for(int i =0; i < playBullets.size(); i++){playBullets.get(i).move();}
}
}
package Game;
import java.awt.Rectangle;
import java.awt.event.ActionListener;
public abstract class Fights extends Location implements ActionListener {
public Fights(Rectangle location) {
super(location);
// TODO Auto-generated constructor stub
}
public Fights(){}
protected int health;
protected int maxHealth;//in the event that I want to have healing items
protected int shotCooldown;//in milliseconds
protected int shotDmg;
protected long currentCool; //cooldown tracker, represents time that shot will be cooled down by (System time # last shot + shotCooldown
protected int xVel, yVel;
public abstract boolean shoot();
public abstract int takeDamage(int damage);//returns remaining health
protected boolean shoots;//determines whether thing can shoot. possible implementation in some enemy class
public boolean move;
public int getHealth(){return health;}
public abstract boolean move();
public int getDamage(){return shotDmg;}
public boolean isDead()
{
return health<=0;
}
}
package Game;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;
public class Location {
protected Rectangle loc;
protected Image image;
public Location(){};
public Location (Rectangle location)
{
loc = location;
}
public Rectangle getLocation()
{
return loc;
}
public void setLocation(Rectangle l)
{
loc = l;
}
public void updateLocation(int x, int y)
{
loc.setLocation(x, y);
}
public Image getImage()
{
return image;
}
public int getX()
{
return (int)loc.getX();
}
public int getY()
{
return (int)loc.getY();
}
}
package Game;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.Rectangle;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
public class Player extends Fights implements KeyListener{
int speed = 4;
public Player(Rectangle location) {
super(location);
GameState.add(this);
image = null;
try{
image = ImageIO.read(new File("ship2.png"));
}catch(IOException e){}
}
public Player(int x, int y) {
maxHealth = 1;
health = maxHealth;
image = null;
try{
image = ImageIO.read(new File("ship2.png"));
}catch(IOException e){}
this.setLocation(new Rectangle(x, y, image.getWidth(null), image.getHeight(null)));
GameState.add(this);
}
public void resetVelocity()
{
xVel = 0;
yVel = 0;
}
#Override
public boolean shoot() {
if(currentCool - System.currentTimeMillis() >0){return false;}
else
{
new Bullet(this);
currentCool = System.currentTimeMillis() + shotCooldown;
}//spawns bullet in the center and slightly in front of player
return true;
}
#Override
public int takeDamage(int damage) {
return health-=damage;
}
#Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
}
#Override
public boolean move() {//moves in a direction only if it won't exceed screen boundary, boolean just in case i need it later
int newX = this.getX(), newY=this.getY();
if((xVel+ this.getX()+this.getLocation().width)<GameState.xLimit()&& this.getX()+xVel>=0)
{
newX +=xVel;
}
if((yVel+ this.getY()+this.getLocation().height)<GameState.yLimit()&& this.getY()+yVel>=0)
{
newY +=yVel;
}
this.updateLocation(newX, newY);
this.resetVelocity();
return true;
}
#Override
public void keyPressed(KeyEvent arg0) {
if (arg0.getKeyCode()== KeyEvent.VK_LEFT)
{
xVel -= speed;
}
if (arg0.getKeyCode()== KeyEvent.VK_RIGHT)
{
xVel += speed;
}
if (arg0.getKeyCode()== KeyEvent.VK_UP)
{
yVel -= speed;
}
if (arg0.getKeyCode()== KeyEvent.VK_DOWN)
{
yVel += speed;
}
if(arg0.getKeyCode()==KeyEvent.VK_SPACE)
{
this.shoot();
}
}
#Override
public void keyReleased(KeyEvent arg0) {
// TODO Auto-generated method stub
}
#Override
public void keyTyped(KeyEvent arg0) {
// TODO Auto-generated method stub
}
}
package Game;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
public class Enemy extends Fights {
public Enemy(Rectangle location) {
super(location);
GameState.add(this);
image = null;
try{
image = ImageIO.read(new File("Enemy-Ship.png"));
}catch(IOException e){}
}
public Enemy(int x, int y, int d) {
image = null;
try{
image = ImageIO.read(new File("Enemy-Ship.png"));
}catch(IOException e){}
this.setLocation(new Rectangle(x, y, image.getWidth(null), image.getHeight(null)));
GameState.add(this);
shotCooldown =(int)(Math.random()*2000);
xVel = (int)((Math.pow(-1, (int)(Math.random())))*((int)(Math.random()*6))+2);
yVel = (int)(Math.random()*3+1);
shotDmg =d;
}
public void actionPerformed(ActionEvent arg0) {
// TODO Auto-generated method stub
}
#Override
public boolean shoot() {
if(currentCool - System.currentTimeMillis() >0){return false;}
else
{
new Bullet(this);
currentCool = System.currentTimeMillis() + shotCooldown;
}//spawns bullet in the center and slightly in front of player
return true;
}
#Override
public int takeDamage(int damage)//returns remaining health
{
health = health-damage;
return health;
}
#Override
public boolean move() {
int newX = this.getX(), newY=this.getY();
if((xVel+ this.getX()+this.getLocation().width)<GameState.xLimit()&& this.getX()+xVel>=0)
{
xVel=-xVel;
newX +=xVel;
}
if(this.getY()+yVel>=0)
{
newY +=yVel;
}
this.updateLocation(newX, newY);
return true;
}
}
package Game;
import java.awt.Rectangle;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
public class Bullet extends Location{
private Fights bulletOwner;
private int damage;
private int velocity;
public Bullet(Fights owner)//eventually change to singleton pattern for efficiency
{
bulletOwner = owner;
damage = owner.getDamage();
image = null;
if(owner instanceof Enemy)
{
try{
image = ImageIO.read(new File("Ebullet.png"));
}catch(IOException e){}
this.setLocation(new Rectangle(owner.getX(), owner.getY()+((int)(owner.getLocation().getHeight()/2)), image.getWidth(null), image.getHeight(null)));
velocity = 5;
}
else
{
try{
image = ImageIO.read(new File("Pbullet.png"));
}catch(IOException e){}
this.setLocation(new Rectangle(owner.getX(), owner.getY()-((int)(owner.getLocation().getHeight()/2)), image.getWidth(null), image.getHeight(null)));
velocity = -15;
}
GameState.add(this);
}
public Fights getOwner(){return bulletOwner;}
public int getDamage(){return damage;}
public int getVelocity(){return velocity;}
public boolean move()
{
this.updateLocation(this.getX(), this.getY()+velocity);
return true;
}
}
I can't believe your write 700 lines of code without doing any testing along the way. Its time you go back to the beginning and start with something simple. That is the whole point of a SSCCE. Start with painting a couple of compononents. Once you get that working you add some movement. Once that is working you add collision logic.
The only thing I noticed with a quick broswe is that you override paintComponents(). There is no need to do that custom painting is done in the pantComponent() method.
If you can't produce a smaller sized SSCCE, then all I can do is wish you good luck.
Ok, so I think I have figured most of it out.
You have a couple problems.
First, you should only see a grey screen with a black rectangle in the middle since you have nothing in your Bullet and Enemy Arrays. This is what I got when I ran your code (after removing references to endEvent cuz it couldn't find it). So to fix this, just give it something to draw
The second problem is apparent once you give it something to draw. I manually put in a line of code to draw the Player, for which I used one of my own pngs. When you do this it will fail to compile with a null pointer exception. The reason is because in your GameView class, you have your Graphics object called "graphics" set to null, but then you proceed to call paintComponents(graphics). As mentioned before, this only compiled before because you never actually drew anything. To fix this, you can just remove
public void paintComponents (Graphics g)
{
for(Bullet j : GameState.getEnBullets()){
g.drawImage(j.getImage(),j.getX(), j.getY(), null);}
for(Enemy j : GameState.getEnemies()){
g.drawImage(j.getImage(),j.getX(), j.getY(), null);}
for(Bullet j : GameState.getPlayBullets()){
g.drawImage(j.getImage(),j.getX(), j.getY(), null);}
this.paint(g);
}
and let the overridden paintComponent(Graphics g) method above it do all the work. Additionally, instead of the paintComponents(graphics) calls, use repaint(). Also you can get rid of the first call to paintComponents(graphics) in the constructor as it will paint the first time by default. If you really want to use your own method then you have to create a Graphics object and pass that in.
Lastly, in the overridden paintComponents(Graphics g) method, you have the last line being to draw the giant black box. This will then cover up anything you've drawn before. So you should have that as the first line and draw everything else in order such that the thing you want to be on top should be drawn last. I was able to get my test image to show up with the following code for that class. I don't think I changed anything else.
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
public class GameView extends JComponent implements ActionListener{
/**
*
*/
private static final long serialVersionUID = -2869672245901003704L;
private boolean liveGame;//used so that buttons cannot be clicked after game is complete
private GameState gs;
private Player p;
private int w, h;
public GameView(int width, int height)
{
liveGame = true;
gs = new GameState();
GameState.init(width, height);
p = new Player(width/2,(height*7)/8);
this.setBackground(Color.BLACK);
w = width;
h = height;
}
#Override
public Dimension getMinimumSize() {
return new Dimension(w, h);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(w, h);
}
#Override
public void paintComponent(Graphics g) {
int margin = 10;
Dimension dim = getSize();
super.paintComponent(g);
g.setColor(Color.black);
GameState.update();
g.fillRect(margin, margin, dim.width - margin * 2, dim.height - margin * 2);
for(Bullet j : GameState.getEnBullets()){
g.drawImage(j.getImage(),j.getX(), j.getY(), null);}
for(Enemy j : GameState.getEnemies()){
g.drawImage(j.getImage(),j.getX(), j.getY(), null);}
for(Bullet j : GameState.getPlayBullets()){
g.drawImage(j.getImage(),j.getX(), j.getY(), null);}
g.drawImage(p.getImage(),p.getX(),p.getY(),null);
}
public void refreshImage()
{
this.removeAll();
repaint();
}
public void actionPerformed(ActionEvent e) {
}
}
The other thing is in some of your other classes you have #Override over the actionPerformed method. My IDE doesn't like that, although it does compile. It says "#Override is not allowed when implementing interface methods."
Hopefully this works for you.
try adding repaint(); after you make a change to a content pane. I dont think concurrency is going to be a problem unless you clog up your EDT.
This is a homework problem. There are a few other java files involved. Note that shapes.Rectangle and shapes.Oval contain a getArea method. I'm having a maddening time trying to figure this out any help is appreciated.
package model;
import java.awt.Color;
import java.awt.Container;
import shapes.Line;
import shapes.Oval;
import shapes.Rectangle;
import shapes.Shape;
import shapes.Triangle;
import interfaces.ComparableShape;
import interfaces.Resettable;
public class Model implements Resettable,ComparableShape {
private Container container;
private String message;
private String action = DRAW;
private boolean fill = false;
private String currentShapeType;
private Shape currentShape;
private Color fillColor = Color.gray;
public Color lineColor;
public final static String DRAW = "Draw";
public final static String MOVE = "Move";
public final static String REMOVE = "Remove";
public final static String RESIZE = "Resize";
public final static String FILL = "Fill";
public final static String CHANGE = "Change";
public final static String RECTANGLE = "Rectangle";
public final static String OVAL = "Oval";
public final static String LINE = "Line";
public final static String TRIANGLE = "Triangle";
public static String[] selections = {"Rectangle", "Oval", "Line", "Triangle"};
//project 9 begin
public Shape[] myShapes = new Shape[2];
//project 9 stop
public Shape createShape() {
if(currentShapeType == RECTANGLE){
currentShape = new Rectangle(0, 0, 0, 0, lineColor, fillColor, fill);
}
if(currentShapeType == OVAL) {
currentShape = new Oval(0,0,0,0, lineColor, fillColor, fill);
}
if(currentShapeType == LINE) {
currentShape = new Line(0,0,0,0, lineColor, fillColor, fill);
}
if(currentShapeType == TRIANGLE) {
currentShape = new Triangle(0,0,0,0, lineColor, fillColor, fill);
}
//project 9 start
if(myShapes[0] == null) {
myShapes[0]=currentShape;
}
else {
myShapes[1]=currentShape;
}
//project 9 stop
return currentShape;
}
public Shape getCurrentShape() {
return currentShape;
}
//project 9 begin
public Shape[] getMyShapearray() {
return myShapes;
}
//project 9 end
public String getCurrentShapeType(){
return currentShapeType;
}
public void setCurrentShapeType(String shapeType){
currentShapeType = shapeType;
}
public Model(Container container) {
this.container = container;
}
public void repaint() {
container.repaint();
}
public String getAction() {
return action;
}
public void setAction(String action) {
this.action = action;
}
public boolean isFill() {
return fill;
}
public void setFill(boolean fill) {
this.fill = fill;
}
public void setMessage(String msg) {
this.message = msg;
}
public String getMessage() {
return this.message;
}
public Color getLineColor() {
return this.lineColor;
}
public void setLineColor(Color c) {
this.lineColor = c;
}
public String toString() {
return "Model:\n\tAction: " + action + "\n\tFill: " + fill + "\n\tArea: " ;
}
public void resetComponents() {
action = DRAW;
currentShape = null;
myShapes = null;
if (container instanceof Resettable) {
((Resettable) container).resetComponents();
}
}
//Add a method to your model called compareShapes(),
//which will return either 0, 1, or 2--1 if the area of the first Shape is bigger than the second,
//2 if it is smaller, and 0 if the two Shapes are the same size.
//Create an interface named ComparableShape that will be used by the shape objects.
//The interface should require implementing classes to have a
//method getArea() capable of returning the area of the object. Obviously, only closed shapes can do this.
//The instanceof operator will be handy here.
public int getArea() {
return getWidth()*getHeight();
}
private int getHeight() {
///what goes here?!
return 0;
}
private int getWidth() {
//what goes here?!
return 0;
}
public int compareShapes(ComparableShape b) {
ComparableShape oneToCompare = null;
if (b instanceof ComparableShape) {
oneToCompare = (ComparableShape)b;
if (getArea() < oneToCompare.getArea()) return 2; // this one is smaller
if (getArea() > oneToCompare.getArea()) return 1; // this one is larger
return 0;
}
return 0;
}
}
Your getArea() should have something like this:-
If currentShapeType is not a LINE (since a line is not closed shape), then calculate and return area of currentShape based on the currentShapeType.
The area of a rectangle is length*width. It's different for the other shapes though. So for a rectangle you need access to its length and width. For a circle you would need its radius. The area of a circle is piR^2.
As someone mentioned below, for an ellipse:
The area of an ellipse is pi*a*b, where a and b are half the length of the major and minor axes. The area of a circle could be written as pi*r*r or pi*r^2 since a and b would be equal.