Java Game Programming Part 2: Disappearing Images - java

For a school computer project I decided make a Pac-Man style game in Java (with two other people). None of us have much experience, so we've essentially been teaching ourselves up to this point. We've made quite a bit of progress, but we seem to have reached a standstill at this point.
How can we make the candies disappear when Fatman runs over them? We've tried using repaint, but we can't seem to get things to work properly.
(I have other things I need help on but they are in different questions)
Thank you for your help!
Here is our code so far:
Maze Class:
package Fatman;
import javax.swing.*;
public class Maze {
public static void main(String[] args){
new Maze();
}
public Maze(){
JFrame f = new JFrame();
f.setTitle("Fatman!");
f.add(new Board());
f.setSize(816, 838);
f.setLocationRelativeTo(null);
f.setVisible(true);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
Map Class
package Fatman;
import java.awt.*;
import java.io.*;
import java.util.*;
import javax.swing.*;
public class Map {
private Scanner m;
private String Map[] = new String[25];
private Image spaceregcandy,
srcb,
safehouse,
spacebigcandy,
blackspace,
space,
portal1,
portal2,
wall;
public Map(){
ImageIcon img = new ImageIcon("C:\\Users\\Martin\\Desktop\\Fatman Project\\spaceregcandy.png");
spaceregcandy = img.getImage();
//image icon has already been initiated, so it doesn't have to be written again
img = new ImageIcon("C:\\Users\\Martin\\Desktop\\Fatman Project\\spaceregcandyblue.png");
srcb = img.getImage();
img = new ImageIcon("C:\\Users\\Martin\\Desktop\\Fatman Project\\safehouse.png");
safehouse = img.getImage();
img = new ImageIcon("C:\\Users\\Martin\\Desktop\\Fatman Project\\wall232x.png");
wall = img.getImage();
img = new ImageIcon("C:\\Users\\Martin\\Desktop\\Fatman Project\\spacebigcandy.png");
spacebigcandy = img.getImage();
img = new ImageIcon("C:\\Users\\Martin\\Desktop\\Fatman Project\\blackspace.png");
blackspace = img.getImage();
img = new ImageIcon("C:\\Users\\Martin\\Desktop\\Fatman Project\\space.png");
space = img.getImage();
img = new ImageIcon("C:\\Users\\Martin\\Desktop\\Fatman Project\\portal1.png");
portal1 = img.getImage();
img = new ImageIcon("C:\\Users\\Martin\\Desktop\\Fatman Project\\portal2.png");
portal2 = img.getImage();
openFile();
readFile();
closeFile();
}
public Image getSpaceregcandy(){
return spaceregcandy;
}
public Image getSrcb(){
return srcb;
}
public Image getSafehouse(){
return safehouse;
}
public Image getWall(){
return wall;
}
public Image getSpacebigcandy(){
return spacebigcandy;
}
public Image getBlackspace(){
return blackspace;
}
public Image getSpace(){
return space;
}
public Image getPortal1(){
return portal1;
}
public Image getPortal2(){
return portal2;
}
public String getMap(int x, int y){
String index = Map[y].substring(x, x + 1);
return index;
//in y position, if y = 2, goes to second row (substring gets x position)
}
public void openFile(){
try{
m = new Scanner(new File("C:\\Users\\Martin\\Desktop\\Fatman Project\\map3.txt"));
}catch(Exception e){
System.out.println("error loading map");
}
}
public void readFile(){
while(m.hasNext()){
for(int i = 0; i < 25; i++){
Map[i] = m.next();
}
}
}
public void closeFile(){
m.close();
}
}
Board Class
package Fatman;
import java.awt.*;
import java.awt.event.*;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import javax.swing.*;
public class Board extends JPanel implements ActionListener{
/**
*
*/
private static final long serialVersionUID = 1L;
private Timer timer;
private Image player;
private Map m;
private Player p;
public Board(){
m = new Map();
p = new Player();
addKeyListener(new Al());
setFocusable(true);
timer = new Timer(1, this);
timer.start();
}
public void actionPerformed(ActionEvent e){
repaint();
}
public void paint(Graphics g){
super.paint(g);
for(int y = 0; y < 25; y++){
for(int x = 0; x <25; x++){
if(m.getMap(x, y).equals("o")){
g.drawImage(m.getSpaceregcandy(), x *32, y *32, null);
}
if(m.getMap(x, y).equals("O")){
g.drawImage(m.getSrcb(), x *32, y *32, null);
}
if(m.getMap(x, y).equals("x")){
g.drawImage(m.getWall(), x *32, y *32, null);
}
if(m.getMap(x, y).equals("H")){
g.drawImage(m.getSafehouse(), x *32, y *32, null);
}
if(m.getMap(x, y).equals("C")){
g.drawImage(m.getSpacebigcandy(), x *32, y *32, null);
}
if(m.getMap(x, y).equals("b")){
g.drawImage(m.getBlackspace(), x *32, y *32, null);
}
if(m.getMap(x, y).equals("s")){
g.drawImage(m.getSpace(), x *32, y *32, null);
}
if(m.getMap(x, y).equals("p")){
g.drawImage(m.getPortal1(), x *32, y *32, null);
}
if(m.getMap(x, y).equals("P")){
g.drawImage(m.getPortal2(), x *32, y *32, null);
}
}
}
g.drawImage(p.getPlayer(), p.getTileX() * 32, p.getTileY() * 32, null);
}
public class Al extends KeyAdapter{
public void keyPressed(KeyEvent e){
int keycode = e.getKeyCode();
if(keycode == KeyEvent.VK_UP){
if(!m.getMap(p.getTileX(), p.getTileY() -1).equals("x")){
if(!m.getMap(p.getTileX(), p.getTileY() -1).equals("b")){
}
p.move(0, -1);
System.out.println(m.getMap(p.getTileX(), p.getTileY()));
}
}
if(keycode == KeyEvent.VK_DOWN){
if(!m.getMap(p.getTileX(), p.getTileY() +1).equals("x")){
if(!m.getMap(p.getTileX(), p.getTileY() +1).equals("b")){
p.move(0, 1);
System.out.println(m.getMap(p.getTileX(), p.getTileY()));
}
}
}
if(keycode == KeyEvent.VK_LEFT){
if(!m.getMap(p.getTileX() - 1, p.getTileY()).equals("x")){
if(!m.getMap(p.getTileX() - 1, p.getTileY()).equals("b")){
p.move(-1, 0);
System.out.println(m.getMap(p.getTileX(), p.getTileY()));
}
}
}
if(keycode == KeyEvent.VK_RIGHT){
if(!m.getMap(p.getTileX() + 1, p.getTileY()).equals("x")){
if(!m.getMap(p.getTileX() + 1, p.getTileY()).equals("b")){
p.move(1, 0);
System.out.println(m.getMap(p.getTileX(), p.getTileY()));
}
}
}
}
public void keyReleased(KeyEvent e){
}
public void keyTyped(KeyEvent e){
}
}
}
Player Class
package Fatman;
import java.awt.Image;
import javax.swing.ImageIcon;
public class Player {
private int tileX, tileY;
private int dx, dy;
private Image player;
public Player(){
ImageIcon img = new ImageIcon("C:\\Users\\Martin\\Desktop\\Fatman Project\\FATMANsimplified32xbrown.png");
player = img.getImage();
tileX = 12;
tileY = 18;
}
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;
}
}
Any ideas?

well i don't think you could be two thirds of a 3 man group, unless you ate one of your members, but on saying that....
Your question is more suited to https://gamedev.stackexchange.com/ as its more of a game development question in my opinion.
However.what you could do, is set the candies position offscreen (for example: candy.x = -100;)
on saying that though, where is your game loop?
public void startGame(){
} public void stopGame(){
} public void update(){ //forces graphics and user input to update the
games state }
also consider going to www.java-gaming.org they have awesome tutorials to help you out.

Nothing in Player.move() is eating dots. You have to update the value of variable Map.Map[] to keep track of what it's supposed to represent. Otherwise this code is just empty words/symbols that hack at doing one instruction from the programmer at a time but don't use the power of a programming language to let the computer do work according to the conditions it meets.

Related

adding time i dont know how to add

Here is my maze code i want to add a timer in my game that if he dosent finish the maze in 60 seconds it will show a game over and the game will stop
Main class
package javamazegame;
import javax.swing.*;
public class JavaMazegame {
public JavaMazegame(){
JFrame f = new JFrame();
f.setTitle("MazeGame Version 1.0");
f.setSize(464,485);
f.add(new Board());
f.setLocationRelativeTo(null);
f.setVisible(true);
f.setResizable(false);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public static void main(String[] args) {
new JavaMazegame();
}
}
how to add a time in my maze game
Board Class
package javamazegame;
import java.awt.*;
import java.awt.event.*;
import javax.swing.Timer;
import javax.swing.*;
public class Board extends JPanel implements ActionListener{
private Timer timer;
private Map m;
private Player p;
public boolean win = false ;
private String Message = " ";
private Font font = new Font("Serif",Font.BOLD,48);
public Board(){
m = new Map();
p = new Player();
addKeyListener(new Al());
setFocusable(true);
timer = new Timer(25,this);
timer.start();
System.out.println(timer);
}
public void actionPerformed(ActionEvent e){
if(m.getMap(p.getTileX(),p.getTileY()).equals("f")){
Message = "Winner";
win = true;
}
repaint();
}
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.GREEN);
g.setFont(font);
g.drawString(Message, 150, 200);
}
}
public class Al extends KeyAdapter{
public void keyPressed(KeyEvent e){
int keycode = e.getKeyCode();
if(keycode == KeyEvent.VK_W){
if(!m.getMap(p.getTileX(),p.getTileY()-1).equals("w")){
p.move(0,-1);
}
}
if(keycode == KeyEvent.VK_S){
if(!m.getMap(p.getTileX(),p.getTileY()+1).equals("w")){
p.move(0,1);
}
}
if(keycode == KeyEvent.VK_A){
if(!m.getMap(p.getTileX()-1,p.getTileY()).equals("w")){
p.move(-1,0);
}
}
if(keycode == KeyEvent.VK_D){
if(!m.getMap(p.getTileX()+1,p.getTileY()).equals("w")){
p.move(1,0);
}
}
}
public void keyRelased(KeyEvent e){
}
public void keyTyped(KeyEvent e){
}
}
}
Map Class
package javamazegame;
import java.awt.*;
import java.io.*;
import java.util.*;
import javax.swing.*;
public class Map {
private Scanner m;
private String Map[] = new String[14];
private Image grass,
finish,
wall;
public Map(){
ImageIcon img = new ImageIcon("C://Users//Rayjay//Desktop//Assets//road.png");
grass = img.getImage();
img = new ImageIcon("C://Users//Rayjay//Desktop//Assets//wall.png");
wall = img.getImage();
img = new ImageIcon("C://Users//Rayjay//Desktop//Assets//finish.png");
finish = img.getImage();
openFile();
readFile();
closeFile();
}
public Image getGrass(){
return grass;
}
public Image getWall(){
return wall;
}
public Image getFinish(){
return finish;
}
public String getMap(int x , int y){
String index = Map[y].substring(x,x+1);
return index;
}
public void openFile(){
try{
m = new Scanner(new File("C://Users//Rayjay//Desktop//Assets//Map.txt"));
}
catch(Exception e){
System.out.println("Error Loading Map");
}
}
public void readFile(){
while(m.hasNext()){
for(int i = 0; i < 14; i++){
Map[i] = m.next();
}
}
}
public void closeFile(){
m.close();
}
}
Player class
package javamazegame;
import java.awt.Image ;
import javax.swing.ImageIcon;
player class this my class for player
public class Player {
private int tileX,tileY;
private Image player;
public Player(){
ImageIcon img = new ImageIcon("C://Users//Rayjay//Desktop//Assets//player.png");
player = img.getImage();
tileX = 1;
tileY = 1;
}
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;
}
}
You could use the Timer class. There are several possibilities how you could work with this class. Here is the doc to Timer.

Space Invaders Alien Array Issue - Java

I am developing a space invaders application for a college assignment and I've come into a problem where the aliens change direction one by one as they hit a wall rather than the whole array of objects switching direction when any alien touches the boundary. I hae a feeling it is an issue in my for loop where my move method containing reverseDirection() method acts on each element individually but I do not know how to fix this and any help would be greatly appreciated. Here is my code for you;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.*;
import javax.swing.*;
import java.awt.image.*;
public class InvadersApplication extends JFrame implements Runnable {//, KeyListener {
private static final Dimension WindowSize = new Dimension(800, 600);
private static final int NUMALIENS = 16;
private Alien AliensArray[] = new Alien[NUMALIENS];
private Image alienImage;
private Image playerImage;
private String workingDirectory = "C:\\Users\\brads\\IdeaProjects\\Assignment3\\src\\workingDirectory\\";
private Player playerShip;
private BufferStrategy strategy;
public InvadersApplication() {
System.out.println(System.getProperty("user.dir"));
setDefaultCloseOperation(EXIT_ON_CLOSE);
Dimension screenSize = java.awt.Toolkit.getDefaultToolkit().getScreenSize();
int x = screenSize.width / 2 - WindowSize.width / 2;
int y = screenSize.height / 2 - WindowSize.height / 2;
setBounds(x, y, WindowSize.width, WindowSize.height);
this.setTitle("Alien Invaders App");
ImageIcon playerIcon = new ImageIcon(workingDirectory + "player_ship.png");
playerImage = playerIcon.getImage();
ImageIcon alienIcon = new ImageIcon(workingDirectory + "alien_ship_1.png");
alienImage = alienIcon.getImage();
playerShip = new Player(playerImage);
// addKeyListener(this);
setVisible(true);
createBufferStrategy(2);
strategy = getBufferStrategy();
for (int i = 0; i < NUMALIENS; i++) {
AliensArray[i] = new Alien(alienImage);
AliensArray[i].setPosition(70 * (i%4), 70 * (i/4));
AliensArray[i].setXspeed(1);
}
Thread thread1 = new Thread(this);
thread1.start();
repaint();
}
#Override
public void run(){
while(true){
try{
for(int i = 0; i < NUMALIENS; i++) {
AliensArray[i].move();
}
repaint();
Thread.sleep(5);
} catch (Exception e) {
e.printStackTrace();
}
}
}
/* public void keyPressed(KeyEvent e) {
int KeyCode = e.getKeyCode();
if (KeyCode == KeyEvent.VK_LEFT) {
playerShip.movePlayer(-8);
} else if (KeyCode == KeyEvent.VK_RIGHT) {
playerShip.movePlayer(8);
}
}
*/
public void keyReleased(KeyEvent e){
}
public void keyTyped(KeyEvent e){}
public void paint(Graphics g){
g = strategy.getDrawGraphics();
g.setColor(Color.BLACK);
g.fillRect(0,0,800,600);
for(int i=0; i < NUMALIENS; i++){
AliensArray[i].paint(g);
}
// playerShip.paint(g);
//playerShip.paintPlayer(g);
strategy.show();
this.repaint();
}
public static void main(String[] args){
InvadersApplication x = new InvadersApplication();
}
}
Sprite2D class;
public class Sprite2D{
protected int x = 0,y = 30;
protected Image myImage;
public Sprite2D(Image myImage){
this.x = x;
this.y = y;
this.myImage = myImage;
}
public void setPosition(int xx, int yy){
x = xx;
y = yy;
}
public void paint(Graphics g){
g.drawImage(myImage, x,y, null);
}
}
Alien subclass of sprite2D;
import java.awt.*;
import java.util.Random;
import javax.swing.*;
public class Alien extends Sprite2D {
private int xi;
private int xj;
public Alien(Image myImage) {
super(myImage);
this.myImage = myImage;
this.x = x;
this.y = y;
this.xi = xi;
this.xj = xj;
}
// #Override
// public void setPosition(int xx, int yy){
// xx = x;
// yy = y;
//
// }
public void move() {
y+=xj;
x+= xi;
if(x >= 750) {
reverseDirection();
x = x + xi;
}
else if (x < 0)
{
reverseDirection();
x = x + xi;
}
}
public void setXspeed(int xi) {
this.xi = xi;
}
public void setYspeed(int xj) {
this.xj = xj;
}
public void reverseDirection() {
xi = -xi;
System.out.println("reverse");
}
// #Override
// public void paint(Graphics g) {
//
//
// g.drawImage(myImage, xx, yy, null);
// }
}

Eclipse Game Lags Too Much

I am making a game and tutorials for how to make it on youtube. Here is the link to the channel. I explain the first part of what I have and why I have it because I know that is helpful for filling you in.
Link to part 1(Then watch the rest of parts. #Chris, this is helpful for solving the problem so don't flag the post).
https://www.youtube.com/watch?v=IRn_ZGhJZ94
I noticed as I was testing out my code for part 4. before recording, the game lagged HORRIBLY. I have alot of code, and any help is appreciated.
Game class:
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import javax.swing.ImageIcon;
import javax.swing.JPanel;
import javax.swing.Timer;
#SuppressWarnings("serial")
public class Game extends JPanel implements ActionListener{
Timer mainTimer;
Paddle paddle;
Ball ball;
int blockCount = 16;
static ArrayList<Block> blocks = new ArrayList<Block>();
public Game() {
setFocusable(true);
paddle = new Paddle(250, 300);
addKeyListener(new KeyAdapt(paddle));
ball = new Ball(275, 280);
mainTimer = new Timer(10, this);
mainTimer.start();
}
public void paint(Graphics g) {
super.paint(g);
Graphics2D g2d = (Graphics2D) g;
ImageIcon ic = new ImageIcon("C:/Users/Elliot/Desktop/Eclipse Game/background.png");
g2d.drawImage(ic.getImage(), 0, 0, null);
paddle.draw(g2d);
ball.draw(g2d);
for(int i = 0; i < blockCount; i++) {
Block b = blocks.get(i);
b.draw(g2d);
}
}
#Override
public void actionPerformed(ActionEvent arg0) {
paddle.update();
ball.update();
for(int i = 0; i < blocks.size(); i++) {
Block b = blocks.get(i);
b.update();
}
repaint();
startGame();
}
public void addBlock(Block b) {
blocks.add(b);
}
public static void removeBlock(Block b) {
blocks.remove(b);
}
public static ArrayList<Block> getBlockList() {
return blocks;
}
public void startGame() {
for(int i = 0; i < blockCount; i++) {
addBlock(new Block(i*60 + 7, 20));
addBlock(new Block(i*60 + 7, 0));
}
}
}
Main class(The frame part):
import javax.swing.JFrame;
public class Main {
public static void main(String[] args) {
JFrame frame = new JFrame("Game");
frame.setSize(500, 400);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new Game());
frame.setResizable(false);
frame.setVisible(true);
}
}
Key Adapt class:
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
public class KeyAdapt extends KeyAdapter{
Paddle p;
public KeyAdapt(Paddle paddle) {
p = paddle;
}
public void keyPressed(KeyEvent e) {
p.keyPressed(e);
}
public void keyReleased(KeyEvent e) {
p.keyReleased(e);
}
}
Paddle class:
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.event.KeyEvent;
import javax.swing.ImageIcon;
public class Paddle {
int velX;
int speed = 3;
static int x1, y1;
public Paddle(int x1, int y1) {
this.x1 = x1;
this.y1 = y1;
}
public void update() {
x1+=velX;
checkCollisions();
}
public void draw(Graphics2D g2d) {
g2d.drawImage(getPaddleImg(), x1, y1, null);
}
public static Image getPaddleImg() {
ImageIcon ic = new ImageIcon("C:/Users/Elliot/Desktop/Eclipse Game/paddle.png");
return ic.getImage();
}
public void keyPressed(KeyEvent e) {
int key = e.getKeyCode();
if(key==KeyEvent.VK_D) {
velX = speed;
} else if(key==KeyEvent.VK_A){
velX = -speed;
}
}
public void keyReleased(KeyEvent e) {
int key = e.getKeyCode();
if(key==KeyEvent.VK_D) {
velX = 0;
} else if(key==KeyEvent.VK_A){
velX = 0;
}
}
public void checkCollisions() {
if(getBounds().getX() + getBounds().getWidth() >= 500) {
x1 = 440;
} else if(getBounds().getX() <= 0) {
x1 = 0;
}
}
public static Rectangle getBounds() {
return new Rectangle(x1, y1 - 1, getPaddleImg().getWidth(null), getPaddleImg().getHeight(null));
}
}
Ball class:
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Rectangle;
import javax.swing.ImageIcon;
import javax.swing.JOptionPane;
public class Ball {
int velX;
int velY;
int speed = 3;
int x, y;
public Ball(int x, int y) {
this.x = x;
this.y = y;
}
public void update() {
x+=velX;
y+=velY;
checkCollisions();
}
public void draw(Graphics2D g2d) {
g2d.drawImage(getBallImg(), x, y, null);
}
public Image getBallImg() {
ImageIcon ic = new ImageIcon("C:/Users/Elliot/Desktop/Eclipse Game/ball.png");
return ic.getImage();
}
public void checkCollisions() {
for(int i = 0; i < Game.getBlockList().size(); i++) {
Block b = Game.getBlockList().get(i);
if(getBounds().intersects(b.getBounds()) && velX!=-speed) {
velY=speed;
velX =- speed;
Game.removeBlock(b);
}
else if(getBounds().intersects(b.getBounds())) {
velY=speed;
velX = speed;
Game.removeBlock(b);
}
}
if(getBounds().intersects(Paddle.getBounds())) {
velY = -speed;
} else if (getBounds().getY() <= 0 && velX!=speed) {
velY = speed;
velX =- speed;
}else if (getBounds().getY() <= 0 && velX!=-speed) {
velY = speed;
velX = speed;
} else if(getBounds().getY() >= 400) {
JOptionPane.showMessageDialog(null, "You Lost! :( ");
System.exit(0);
}
if(getBounds().getX() <= 0) {
velX = speed;
} else if(getBounds().getX() >= 500 - getBounds().getWidth()) {
velX = -speed;
}
}
public Rectangle getBounds() {
return new Rectangle(x, y, getBallImg().getWidth(null), getBallImg().getHeight(null));
}
}
Block class:
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Rectangle;
import javax.swing.ImageIcon;
public class Block {
int x2, y2;
public Block(int x2, int y2) {
this.x2 = x2;
this.y2 = y2;
}
public void update() {
}
public void draw(Graphics2D g2d){
g2d.drawImage(getBlockImg(), x2, y2, null);
}
public static Image getBlockImg() {
ImageIcon ic = new ImageIcon("C:/Users/Elliot/Desktop/Eclipse Game/block.png");
return ic.getImage();
}
public Rectangle getBounds() {
return new Rectangle(x2, y2, getBlockImg().getWidth(null), getBlockImg().getHeight(null));
}
}
I also have a folder called Eclipse Game on my desktop and I refer to it in my code.
Again, I understand this is alot but any idea with making it lag less is helpful. Also, watching the tutorial (look at the beginning for the link) on making what I have finished so far will help make it less confusing for you to understand how the code works. The game seriously lags so much I cannot play.
There are multiple issues.
The first, as I already mentioned in my comment, is that you're calling startGame() inside your timer action listener:
#Override
public void actionPerformed(ActionEvent arg0) {
paddle.update();
ball.update();
for(int i = 0; i < blocks.size(); i++) {
Block b = blocks.get(i);
b.update();
}
repaint();
startGame();
}
This is adding 3,200 blocks every second to the game, so you don't want that. I think the simplest place to put startGame() is at the end of the game constructor:
public Game() {
setFocusable(true);
paddle = new Paddle(250, 300);
addKeyListener(new KeyAdapt(paddle));
ball = new Ball(275, 280);
mainTimer = new Timer(10, this);
mainTimer.start();
startGame();
}
The other really big problem is that you're constantly reloading the images all the time. For example, look at this snippet:
if(getBounds().intersects(b.getBounds()) && velX!=-speed) {
velY=speed;
velX =- speed;
Game.removeBlock(b);
}
else if(getBounds().intersects(b.getBounds())) {
velY=speed;
velX = speed;
Game.removeBlock(b);
}
That is 4 calls to getBounds(), and if we take a look at that:
return new Rectangle(x2, y2, getBlockImg().getWidth(null), getBlockImg().getHeight(null));
You are loading 2 images which in total is 4*2*blockCount images every 10ms, just for this one method. Instead of loading images all the time, do something like this:
class GameResources {
static Image ballImage;
static Image paddleImage;
static Image blockImage;
// call GameResources.loadResources() at the
// beginning of main() or something
static void loadResources() {
// load all 3 images once here and be done
ballImage = ...;
paddleImage = ...;
blockImage = ...;
}
Then finally, you have an issue with removing items from the list while iterating over it, Ball.checkCollisions:
for(int i = 0; i < Game.getBlockList().size(); i++) {
Block b = Game.getBlockList().get(i);
if(getBounds().intersects(b.getBounds()) && velX!=-speed) {
velY=speed;
velX =- speed;
// removeBlock changes blocks.size()
Game.removeBlock(b);
}
else if(getBounds().intersects(b.getBounds())) {
velY=speed;
velX = speed;
// removeBlock changes blocks.size()
Game.removeBlock(b);
}
}
Instead you need to do something like this:
Iterator<Block> iter = Game.getBlockList().iterator();
while (it.hasNext()) {
Block b = it.next();
if(getBounds().intersects(b.getBounds()) && velX!=-speed) {
velY=speed;
velX =- speed;
// safely removing
it.remove();
}
else if(getBounds().intersects(b.getBounds())) {
velY=speed;
velX = speed;
// safely removing
it.remove();
}
}
And another possible boundary issue in Game.paint:
// using blockCount after possibly
// removing items from the list
// vvvvvvvvvv
for(int i = 0; i < blockCount; i++) {
Block b = blocks.get(i);
b.draw(g2d);
}
For simple iterations like this, you should use for-each:
for(Block b : blocks) {
b.draw(g2d);
}
After all of that the game runs pretty smoothly, except for some type of issue with the key listener which I didn't have time to figure out. I might look at it again after dinner.
edit:
I noticed a lot of other small things, so here is the program fixed up a bit more with my comments.
Some of the classes aren't public anymore just because I had them all in one source file.
import javax.swing.SwingUtilities;
import javax.swing.Timer;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JOptionPane;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyAdapter;
import java.util.ArrayList;
import java.util.Iterator;
import java.awt.Rectangle;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Dimension;
import java.net.URL;
import javax.imageio.ImageIO;
import java.io.IOException;
import java.io.File;
public class BlockGame {
public static void main(String[] args) {
// Swing program should always begin on the Swing
// thread with a call to invokeLater.
// See https://docs.oracle.com/javase/tutorial/uiswing/concurrency/initial.html
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
try {
// change this to
// .loadImages();
GameResources.loadInternetImages();
} catch (IOException x) {
x.printStackTrace();
return;
}
JFrame frame = new JFrame("Game");
// frame.setSize(500, 400);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// frame.add(new Game());
// Instead of calling setSize on the JFrame
// directly, set a preferred size on the game
// panel, then call pack() on the JFrame
Game game = new Game();
game.setPreferredSize(new Dimension(500, 400));
frame.add(game);
frame.pack();
frame.setResizable(false);
frame.setVisible(true);
// I started the game here instead
// of in the game loop, so the panel
// is visible and stuff beforehand.
game.startGame();
}
});
}
}
class Game extends JPanel implements ActionListener {
Timer mainTimer;
Paddle paddle;
Ball ball;
// I removed this because it's only ever
// used by startGame.
// int blockCount = 16;
// I changed this to an instance variable
// (not static) and passed the game in to
// update so the game objects can access
// it.
ArrayList<Block> blocks = new ArrayList<Block>();
public Game() {
setFocusable(true);
paddle = new Paddle(250, 300);
addKeyListener(new KeyAdapt(paddle));
ball = new Ball(275, 280);
mainTimer = new Timer(10, this);
// I moved this to the startGame() method
// mainTimer.start();
}
// Swing programs should override paintComponent
// instead of paint.
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
// You should create a copy instead of
// directly using the graphics object which
// the component uses.
// This is so any changes you make to it
// don't affect the Swing paint routines.
Graphics2D g2d = (Graphics2D) g.create();
// ImageIcon ic = new ImageIcon("C:/Users/Elliot/Desktop/Eclipse Game/background.png");
// g2d.drawImage(ic.getImage(), 0, 0, null);
// Painting static resource.
g2d.drawImage(GameResources.backgroundImage, 0, 0, null);
paddle.draw(g2d);
ball.draw(g2d);
// This loop will throw an out of bounds
// exception once the first block is removed.
// vvvvvvvvvv
// for(int i = 0; i < blockCount; i++) {
// Block b = blocks.get(i);
// b.draw(g2d);
// }
// using for each
for (Block b : blocks) {
b.draw(g2d);
}
// Dispose the copied graphics when you're done.
g2d.dispose();
}
#Override
public void actionPerformed(ActionEvent arg0) {
paddle.update(this);
ball.update(this);
// for(int i = 0; i < blocks.size(); i++) {
// Block b = blocks.get(i);
// b.update();
// }
for (Block b : blocks) {
b.update(this);
}
repaint();
// I moved this to main
// startGame();
}
public void addBlock(Block b) {
blocks.add(b);
}
public void removeBlock(Block b) {
blocks.remove(b);
}
public ArrayList<Block> getBlockList() {
return blocks;
}
// I added this method so that the
// ball can access the paddle without
// static variables.
public Paddle getPaddle() {
return paddle;
}
public void startGame() {
// So the method won't be called twice
// and put the game in some unexpected
// state.
if (mainTimer.isRunning()) {
throw new IllegalStateException("game already started");
}
int initialBlockCount = 16;
for(int i = 0; i < initialBlockCount; i++) {
addBlock(new Block(i*60 + 7, 20));
addBlock(new Block(i*60 + 7, 0));
}
mainTimer.start();
}
}
// Generally speaking you should use
// Swing key bindings now, instead of
// key listeners.
//
// Key listeners have problems with
// the focus system: Swing components
// only send out key events when they
// have the focus.
//
// Key bindings don't have this issue.
//
// You can set up key bindings so they
// trigger any time the key is pressed
// in the focused window.
//
// https://docs.oracle.com/javase/tutorial/uiswing/misc/keybinding.html
//
class KeyAdapt extends KeyAdapter {
Paddle p;
public KeyAdapt(Paddle paddle) {
p = paddle;
}
public void keyPressed(KeyEvent e) {
p.keyPressed(e);
}
public void keyReleased(KeyEvent e) {
p.keyReleased(e);
}
}
class Paddle {
int velX;
int speed = 3;
// I changed these from static
// to instance variables.
int x1, y1;
// I added these variables to
// help with the key listener
// logic.
boolean leftPressed, rightPressed;
public Paddle(int x1, int y1) {
this.x1 = x1;
this.y1 = y1;
}
public void update(Game game) {
x1 += velX;
checkCollisions();
}
public void draw(Graphics2D g2d) {
g2d.drawImage(GameResources.paddleImage, x1, y1, null);
}
// public static Image getPaddleImg() {
// ImageIcon ic = new ImageIcon("C:/Users/Elliot/Desktop/Eclipse Game/paddle.png");
// return ic.getImage();
// }
public void keyPressed(KeyEvent e) {
int key = e.getKeyCode();
// This logic is a little more robust
// because it handles cases where both
// keys are being held at the same time.
// Also see computeVelX().
if (key == KeyEvent.VK_D) {
leftPressed = true;
// velX = speed;
} else if (key == KeyEvent.VK_A) {
rightPressed = true;
// velX = -speed;
}
computeVelX();
}
public void keyReleased(KeyEvent e) {
int key = e.getKeyCode();
// This logic is a little more robust
// because it handles cases where both
// keys are being held at the same time.
// Also see computeVelX().
if (key == KeyEvent.VK_D) {
leftPressed = false;
// velX = 0;
} else if (key == KeyEvent.VK_A) {
rightPressed = false;
// velX = 0;
}
computeVelX();
}
public void computeVelX() {
// This way the keys will never
// "stick". If both keys are
// held at the same time, velX
// is just 0 until one of the
// keys is released.
velX = 0;
if (leftPressed) {
velX += speed;
}
if (rightPressed) {
velX -= speed;
}
}
public void checkCollisions() {
// I used a variable instead of calling
// getBounds() repeatedly.
Rectangle bounds = getBounds();
if (bounds.getX() + bounds.getWidth() >= 500) {
x1 = 440;
} else if (bounds.getX() <= 0) {
x1 = 0;
}
}
// I change this from static to an instance method.
public Rectangle getBounds() {
// return new Rectangle(x1, y1 - 1, getPaddleImg().getWidth(null), getPaddleImg().getHeight(null));
int width = GameResources.paddleImage.getWidth(null);
int height = GameResources.paddleImage.getHeight(null);
return new Rectangle(x1, y1 - 1, width, height);
}
}
class Ball {
int velX;
int velY;
int speed = 3;
int x, y;
public Ball(int x, int y) {
this.x = x;
this.y = y;
}
public void update(Game game) {
x += velX;
y += velY;
checkCollisions(game);
}
public void draw(Graphics2D g2d) {
// g2d.drawImage(getBallImg(), x, y, null);
g2d.drawImage(GameResources.ballImage, x, y, null);
}
// public Image getBallImg() {
// ImageIcon ic = new ImageIcon("C:/Users/Elliot/Desktop/Eclipse Game/ball.png");
// return ic.getImage();
// }
public void checkCollisions(Game game) {
// Using an iterator instead of looping with size()
// directly, because we want to remove items from
// the list while iterating.
// The problem with removing while iterating with
// size() is that once you remove an element, the
// list shifts all the other elements back by 1,
// so on the next iteration of the loop you end
// up skipping an item.
// (Say you remove the element at index 5. Then
// all the elements shift back, so that e.g. the
// element at index 6 is now at index 5. The variable
// i is incremented, so you end up skipping the element
// that was at index 6 before the removal.
Iterator<Block> iter = game.getBlockList().iterator();
Rectangle bounds = getBounds();
while (iter.hasNext()) {
Block b = iter.next();
Rectangle bBounds = b.getBounds();
if (bounds.intersects(bBounds) && velX != -speed) {
velY = speed;
velX =- speed;
// Game.removeBlock(b);
iter.remove();
} else if (bounds.intersects(bBounds)) {
velY = speed;
velX = speed;
// Game.removeBlock(b);
iter.remove();
}
}
//
Rectangle pBounds = game.getPaddle().getBounds();
if (bounds.intersects(pBounds)) {
velY = -speed;
} else if (bounds.getY() <= 0 && velX != speed) {
velY = speed;
velX =- speed;
} else if (bounds.getY() <= 0 && velX != -speed) {
velY = speed;
velX = speed;
} else if (bounds.getY() >= 400) {
JOptionPane.showMessageDialog(null, "You Lost! :( ");
System.exit(0);
}
if (bounds.getX() <= 0) {
velX = speed;
} else if(bounds.getX() >= 500 - bounds.getWidth()) {
velX = -speed;
}
}
public Rectangle getBounds() {
// return new Rectangle(x, y, getBallImg().getWidth(null), getBallImg().getHeight(null));
int width = GameResources.ballImage.getWidth(null);
int height = GameResources.ballImage.getHeight(null);
return new Rectangle(x, y, width, height);
}
}
class Block {
int x2, y2;
public Block(int x2, int y2) {
this.x2 = x2;
this.y2 = y2;
}
public void update(Game game) {
}
public void draw(Graphics2D g2d){
// g2d.drawImage(getBlockImg(), x2, y2, null);
g2d.drawImage(GameResources.blockImage, x2, y2, null);
}
// public static Image getBlockImg() {
// ImageIcon ic = new ImageIcon("C:/Users/Elliot/Desktop/Eclipse Game/block.png");
// return ic.getImage();
// }
public Rectangle getBounds() {
// return new Rectangle(x2, y2, getBlockImg().getWidth(null), getBlockImg().getHeight(null));
int width = GameResources.blockImage.getWidth(null);
int height = GameResources.blockImage.getHeight(null);
return new Rectangle(x2, y2, width, height);
}
}
class GameResources {
public static Image backgroundImage;
public static Image blockImage;
public static Image ballImage;
public static Image paddleImage;
public static void loadImages() throws IOException {
// Load images once here.
// I didn't test this method since I don't have the images, but it
// should work. ImageIO.read will give better error messages than
// using ImageIcon. ImageIcon.getImage() will just return null if
// there was a problem, which doesn't tell you what the problem
// actually was.
paddleImage =
ImageIO.read(new File("C:/Users/Elliot/Desktop/Eclipse Game/paddle.png"));
ballImage =
ImageIO.read(new File("C:/Users/Elliot/Desktop/Eclipse Game/ball.png"));
blockImage =
ImageIO.read(new File("C:/Users/Elliot/Desktop/Eclipse Game/block.png"));
backgroundImage =
ImageIO.read(new File("C:/Users/Elliot/Desktop/Eclipse Game/background.png"));
}
public static void loadInternetImages() throws IOException {
// These images are from
// http://stackoverflow.com/questions/19209650/example-images-for-code-and-mark-up-qas
paddleImage =
ImageIO.read(new URL("http://i.stack.imgur.com/gYxHm.png"));
ballImage =
ImageIO.read(new URL("http://i.stack.imgur.com/gJmeJ.png"));
blockImage =
ImageIO.read(new URL("http://i.stack.imgur.com/F0JHK.png"));
backgroundImage =
ImageIO.read(new URL("http://i.stack.imgur.com/P59NF.png"));
}
}

How can i add time limitation in a Maze Game using java

I am making a maze game in Java. I have made a maze board, A start point and a end point. When I reach the end point then it exit and show a winning message. But I can not add a time limitation. Suppose player have to reach the end point with 30 seconds otherwise he lose the game. Please help me.
Here is my code i have done so far.......
Maze.java
package Maze;
import javax.swing.JFrame;
public class Maze {
public static void main(String args[])
{
new Maze();
}
public Maze()
{
JFrame f= new JFrame();
f.setTitle("Maze Game");
f.add(new Board());
f.setSize(460,480);
f.setLocationRelativeTo(f);
f.setVisible(true);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
Board.java
package Maze;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
// #SuppressWarnings("serial")
#SuppressWarnings("serial")
public class Board extends JPanel implements ActionListener
{
private Timer timer;
private Map m;
private Player p;
private boolean win=false;
long startTime = System.currentTimeMillis();
long elapsedTime;
//private String Message="";
//private Font font=new Font("Serif",Font.BOLD,50);
public Board()
{
long elapsedTime = System.currentTimeMillis() - startTime;
elapsedTime=elapsedTime/1000;
m= new Map();
p= new Player();
addKeyListener(new Al());
setFocusable(true);
timer=new Timer(25, this);
timer.start();
}
public void actionPerformed(ActionEvent e)
{
if(m.getMap(p.getTileX(), p.getTileY()).equals("f"))
{
//Message="WINNER";
win=true;
}
if(elapsedTime>=5)
win=true;
repaint();
}
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("w"))
g.drawImage(m.getWall(), x*32, y*32, null);
if(m.getMap(x, y).equals("g"))
g.drawImage(m.getGrass(), x*32, y*32, null);
}
}
g.drawImage(p.getPlayer(), p.getTileX()*32, p.getTileY()*32,null);
}
if(win)
{
g.drawImage(m.getWinn(), 32, 32, null);
// g.setColor(Color.ORANGE);
//g.setFont(font);
//g.drawString(Message, 150, 200);
}
}
public class Al extends KeyAdapter{
public void keyPressed(KeyEvent e){
int keycode= e.getKeyCode();
if(keycode==KeyEvent.VK_UP ){
if(!m.getMap(p.getTileX(),p.getTileY()-1).equals("w")){
p.move( 0, -1);
}
}
if(keycode==KeyEvent.VK_DOWN ){
if(!m.getMap(p.getTileX(),p.getTileY()+1).equals("w")){
p.move( 0, 1);
}
}
if(keycode==KeyEvent.VK_LEFT ){
if(!m.getMap(p.getTileX()-1,p.getTileY()).equals("w")){
p.move( -1, 0);
}
}
if(keycode==KeyEvent.VK_RIGHT ){
if(!m.getMap(p.getTileX()+1,p.getTileY()).equals("w")){
p.move( 1, 0 );
}
}
}
/* public void keyRealeased(KeyEvent e){
}
public void keyTyped(KeyEvent e){
}*/
}
}
Map.java
package Maze;
import java.awt.*;
import java.io.*;
import java.util.*;
import javax.swing.ImageIcon;
public class Map {
private Scanner m;
private String Map[]=new String[14];
private Image grass,wall,finish,winn;
public Map(){
ImageIcon img = new ImageIcon("C://project//7.jpg");
grass = img.getImage();
img = new ImageIcon("C://project//2.jpg");
wall = img.getImage();
img=new ImageIcon("C://project//hell.gif");
finish=img.getImage();
img=new ImageIcon("C://project//12.jpg");
winn=img.getImage();
openfile();
readfile();
closefile();
}
public Image getGrass()
{
return grass;
}
public Image getWall()
{
return wall;
}
public Image getFinish()
{
return finish;
}
public Image getWinn()
{
return winn;
}
public String getMap(int x, int y){
String index=Map[y].substring(x, x+1);
return index;
}
public void openfile(){
try {
m = new Scanner(new File("C://project//Map.txt"));
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
//e.printStackTrace();
System.out.println("Error loading file.");
}
}
public void readfile(){
while(m.hasNext()){
for(int i=0;i<14;i++){
Map[i]=m.next();
}
}
}
public void closefile(){
m.close();
}
}
Player.java
package Maze;
import java.awt.Image;
import javax.swing.ImageIcon;
public class Player {
private int tilex,tiley;
private Image player;
public Player(){
ImageIcon img=new ImageIcon("C://project//5990.gif");
player=img.getImage();
tilex=1;
tiley=1;
}
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;
}
}
and here is the .txt file
Map.txt
wwwwwwwwwwwwww
wggggggwgggggw
wggwwggwgwwggw
wwgggwwwggwggw
wgwgggggggwwgw
wgggwggwwwgggw
wgggwgggwggwww
wggwggwwwggggw
wgwwgggggwwggw
wgggggwwwgwggw
wggwggggwgwwgw
wwwwgwwwwggwgw
wggggwgfgggggw
wwwwwwwwwwwwww
You can do a work around ,Add a timer class which will execute at x seconds and keep on calculating the total seconds in a variable and when the limit is crossed you can stop your program.

Graphics not appearing in JFrame (SSCCE included)

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.

Categories

Resources