angry-flappy-bird/src/Engine/GameEngine.java

263 lines
5.7 KiB
Java

package Engine;
import Sprites.*;
import javax.swing.*;
import java.applet.Applet;
import java.applet.AudioClip;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import java.net.URL;
import java.util.Random;
import java.util.Vector;
/**
* Created by sagi on 12/18/15.
*/
public class GameEngine extends MouseAdapter {
private final int PIPE_ACC = 10, PIPE_WIDTH = 90, PIPE_INTERVAL_TIME = 2000;
public boolean gameOn , gameOver, isFirstGame, canScore;
private Bird bird;
private Vector<Sprite> pipes; //will save all laser shots and asteroids which are currently on the screen.
private int pWidth, pHeight; //panel dimensions
private Timer pipeTimer; //interval to create new pipe
private Random r;
private int score;
private BufferedImage sceneImage;
private int heighScore;
private Vector<SideScollerBackground> backgrounds; //Background elements
private Vector<AudioClip> successSounds;
private AudioClip themeAudioClip;
private final URL themeURL= getClass().getResource("/Sounds/theme.wav");
public GameEngine(int width, int height){
//initialize variables and load audio\image files.
this.canScore = true;
this.isFirstGame = true;
this.gameOver = true;
this.pWidth = width;
this.pHeight = height;
try {
themeAudioClip = Applet.newAudioClip(themeURL);
}catch (Exception e){
themeAudioClip = null;
}
if(themeAudioClip != null) {
themeAudioClip.loop();
}
r = new Random();
sceneImage = new BufferedImage(width, height, Image.SCALE_SMOOTH);
loadSuccessSounds();
startNewGame();
heighScore = 0;
}
/**
* initialize and reset vars and timers to "new game" configuration.
*/
private void startNewGame(){
this.gameOn = true;
pipeTimer = new Timer(PIPE_INTERVAL_TIME, new PipeTimerListener());
backgrounds = new Vector<>();
initBackgrounds();
initGame();
}
/**
* Setup all actors in the game to a new game - reset timer
*/
private void initGame(){
pipes = new Vector<>();
this.bird = new Bird(100, this.pWidth, this.pHeight, 45);
this.score = 0;
gameOn = true;
pipeTimer.start();
}
// Loads soundFX Vector
private void loadSuccessSounds(){
successSounds = new Vector<>();
for (int i = 1 ; i < 5 ; i++){
successSounds.add(Applet.newAudioClip(getClass().getResource("/Sounds/pass"+i+".wav")));
}
}
//initialize background Sprites
private void initBackgrounds(){
backgrounds.add(new SideScollerBackground(pWidth, pHeight, 2, "skyLine.png", pWidth, pHeight));
backgrounds.add(new SideScollerBackground(pWidth, pHeight, 5, "trees.png", pWidth + 50, pHeight));
backgrounds.add(new SideScollerBackground(pWidth, pHeight, 10, "ground.png", pWidth, 45));
}
/**
* returns score
* @return
* int
*/
public int getScore(){
return score;
}
/**
* returns gameOver flag
* @return
* boolean
*/
public boolean isGameOver(){
return this.gameOver;
}
public int getHeighScore() { return this.heighScore;}
/**
* Create a new Pipe on a random position.
*/
private void createPipe(){
int pipeLoc = (r.nextInt(pHeight-40)+40) * -1;
pipes.add(new Pipe(pipeLoc, pWidth, pHeight, PIPE_ACC, PIPE_WIDTH, pHeight * 2));
}
/**
* Update all sprites, including collision handling.
*/
public void update(){
if(!gameOver) {
bird.update();
for(int i=0; i<pipes.size(); i++){
pipes.elementAt(i).update();
}
for(int i = 0 ; i < backgrounds.size() ; i++){
backgrounds.elementAt(i).update();
}
collisionHandler();
}
}
/**
* Checks if a collision has occurred.
* in case of missile hitting an asteroid - they are both removed.
* in case of asteroid hitting the ship - round over.
*/
private void collisionHandler() {
//Ikaros - dont fly too high, dont fly to low.
if (bird.getLocY() >= pHeight - ( bird.getSWidth() + backgrounds.lastElement().getsHeight())|| bird.getLocY() <= 0) {
pipeTimer.stop();
gameOver = true;
heighScore = score > heighScore ? score : heighScore;
}
//pipe out of screen
if (!pipes.isEmpty() && pipes.elementAt(0).getLocX() + PIPE_WIDTH < 0) {
canScore = true;
pipes.remove(0);
}
//pipe vs. bird
if (!pipes.isEmpty() && CollisionUtil.collidesWith(bird, pipes.elementAt(0))){
gameOver = true;
pipeTimer.stop();
heighScore = score > heighScore ? score : heighScore;
}
//passed the pipe?
if(canScore && !pipes.isEmpty() && bird.getLocX() >= pipes.elementAt(0).getLocX() + pipes.elementAt(0).getSWidth()) {
score++;
canScore = false;
successSounds.elementAt(r.nextInt(4)).play();
heighScore = score > heighScore ? score : heighScore;
}
}
/**
* render buffered image.
* @param panel
* JPanel
*/
public void render(JPanel panel){
sceneImage = new BufferedImage(this.pWidth, this.pHeight, Image.SCALE_FAST); // Empty Scene
renderScene(sceneImage.getGraphics(), panel); // Paint new Scene
}
/**
* Draws all sprites
* @param g
* Graphics
* @param panel
* Jpanel
*/
public void renderScene(Graphics g, JPanel panel){
backgrounds.elementAt(0).drawSprite(g, panel);
backgrounds.elementAt(1).drawSprite(g, panel);
bird.drawSprite(g, panel);
for(int i=0; i<pipes.size(); i++){
pipes.elementAt(i).drawSprite(g, panel);
}
backgrounds.elementAt(2).drawSprite(g, panel);
}
/**
* creates an new asteroid each 5 seconds *
*/
private class PipeTimerListener implements ActionListener{
@Override
public void actionPerformed(ActionEvent actionEvent) {
createPipe();
}
}
//mouse clicked starts game Or jumps
public void mousePressed(MouseEvent e){
if(gameOver){
this.isFirstGame = false;
gameOver = false;
initGame();
} else {
bird.jump();
}
}
/**
* returns sceneImage
* @return
* BufferedImage
*/
public BufferedImage getScene(){
return this.sceneImage;
}
}