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;
}
}