commit 86e924f2cb8facebd83a403d508b6bbc1d9952f2 Author: Sagi Dayan Date: Sat Feb 27 22:45:32 2016 +0200 Initial commit - Skeleton of the game diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..8117b8f --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +.idea/ +out/ +*.iml diff --git a/src/com/sagi/dayan/Games/Elements/AnimatedDemoSprite.java b/src/com/sagi/dayan/Games/Elements/AnimatedDemoSprite.java new file mode 100644 index 0000000..70d646a --- /dev/null +++ b/src/com/sagi/dayan/Games/Elements/AnimatedDemoSprite.java @@ -0,0 +1,55 @@ +package com.sagi.dayan.Games.Elements; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +/** + * Created by sagi on 2/10/16. + */ +public class AnimatedDemoSprite extends AnimatedSprite { + + private int timerCouner = 0; + protected Timer t; + + public AnimatedDemoSprite(int x, int y, int w, int h, int acc, String imgName, double angle, int sWidth, int sHeight) { + super(x, y, w, h, acc, imgName, angle, sWidth, sHeight); + setScreenLoop(true); + animations.add(new Animation("animatedSample2.png", 16, 2000)); + t = new Timer(1 * 1000, new TimerTick()); + t.start(); + } + + @Override + public void update() { + locX += acceleration; + } + + @Override + protected void initFirstAnimation(String spriteSheet) { + animations.add(new Animation(spriteSheet, 8, 1 * 1000)); + } + + private class TimerTick implements ActionListener { + + @Override + public void actionPerformed(ActionEvent actionEvent) { + if(timerCouner < 5){ + timerCouner++; + } + else if(5 <= timerCouner && timerCouner < 7){ + System.out.println("Explode"); + timerCouner++; + currentAnimation = 1; + acceleration = 0; + }else{ + currentAnimation = 0; + timerCouner = 0; + acceleration = 5; + } + } + } + + +} diff --git a/src/com/sagi/dayan/Games/Elements/AnimatedSprite.java b/src/com/sagi/dayan/Games/Elements/AnimatedSprite.java new file mode 100644 index 0000000..2437cae --- /dev/null +++ b/src/com/sagi/dayan/Games/Elements/AnimatedSprite.java @@ -0,0 +1,134 @@ +package com.sagi.dayan.Games.Elements; + +import javax.imageio.ImageIO; +import javax.swing.*; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.image.BufferedImage; +import java.io.IOException; +import java.util.Vector; + +/** + * Created by sagi on 2/10/16. + */ +public abstract class AnimatedSprite extends Sprite { + protected Vector animations; + protected int currentAnimation; + + + public AnimatedSprite(int x, int y, int w, int h, int acc, String imgName, double angle, int sWidth, int sHeight) { + super(x, y, w, h, acc, imgName, angle, sWidth, sHeight); + animations = new Vector<>(); + initFirstAnimation(imgName); + currentAnimation = 0; + + } + + protected abstract void initFirstAnimation(String spriteSheet); + + @Override + public void drawSprite(Graphics g, JPanel p) { + if(animations.size() == 0) + return; + Graphics2D g2d = (Graphics2D) g; + g2d.rotate(Math.toRadians(angle), locX + (bImage.getWidth() / 2), locY + (bImage.getHeight() / 2)); + g.drawImage(animations.get(currentAnimation).getCurrentFrame(), locX, locY, p); + g2d.rotate(-1 * Math.toRadians(angle), locX + (bImage.getWidth() / 2), locY + (bImage.getHeight() / 2)); + if(screenLoop) { + drawScreenLoopFix(g, p); + outOfScreeFix(); + } + } + + @Override + protected void drawScreenLoopFix(Graphics g, JPanel p) { + bImage = animations.get(currentAnimation).getCurrentFrame(); + super.drawScreenLoopFix(g,p); + } + + public void setCurrentAnimation(int animation){ + if(animation < 0){ + throw new IllegalArgumentException("Animation index cant be negative"); + }else if(animation >= animations.size()){ + throw new IllegalArgumentException("Number of animations is: "+ animations.size() + 1+". " +animation +"is out the limit"); + }else{ + currentAnimation = animation; + } + } + + + + protected class Animation { + + private int totalLoopTime; + private Vector frames; + private int currentFrame; + private long startingTime; + private BufferedImage spriteSheet; + + public Animation(String spriteSheetName, int numOfFrames, int totalAnimationTime) { + this.currentFrame = 0; + this.totalLoopTime = 0; + this.startingTime = System.currentTimeMillis(); + this.frames = new Vector<>(); + + //load image from source files + try { + spriteSheet = ImageIO.read(getClass().getResource("/com/sagi/dayan/Games/Images/" + spriteSheetName)); + } catch (IOException pin) { + pin.printStackTrace(); + spriteSheet = null; + } + int frameHeight = spriteSheet.getHeight(); + int frameWidth = spriteSheet.getWidth() / numOfFrames; + int currentX = 0; + for(int i = 0 ; i < numOfFrames ; i++) { + addFrame(spriteSheet.getSubimage(currentX, 0, frameWidth, frameHeight), (double)totalAnimationTime/numOfFrames); + currentX += frameWidth; + } + + + } + + public int getFrameIndex() { return currentFrame;} + + private void addFrame(BufferedImage image, double frameLength) { + frames.add(new AnimationFrame(image, totalLoopTime,frameLength)); + totalLoopTime += frameLength; + } + + public BufferedImage getCurrentFrame() { + long now = System.currentTimeMillis(); + long delta = now - startingTime; + while( !( frames.get(currentFrame).getStartTime() <= delta && delta < frames.get(currentFrame).getEndTime() ) ){ + currentFrame++; + if(currentFrame >= frames.size()) { + currentFrame = 0; + startingTime = now; + return frames.get(currentFrame).getFrame(); + } + } + return frames.get(currentFrame).getFrame(); + } + + protected class AnimationFrame { + private double startTime, endTime; + private BufferedImage frame; + + public AnimationFrame(BufferedImage image, double startTime , double frameLength){ + this.startTime = startTime; + this.endTime = this.startTime + frameLength; + this.frame = image; + } + + public double getStartTime() { return startTime;} + public double getEndTime() { return endTime;} + public BufferedImage getFrame() {return frame;} + + } + + } + + +} diff --git a/src/com/sagi/dayan/Games/Elements/Background.java b/src/com/sagi/dayan/Games/Elements/Background.java new file mode 100644 index 0000000..42a0411 --- /dev/null +++ b/src/com/sagi/dayan/Games/Elements/Background.java @@ -0,0 +1,19 @@ +package com.sagi.dayan.Games.Elements; + +/** + * Created by sagi on 2/20/16. + */ +public class Background extends Sprite { + public Background(int x, int y, int w, int h, int acc, String imgName, double angle, int sWidth, int sHeight) { + super(x, y, w, h, acc, imgName, angle, sWidth, sHeight); + locX = 0; + locY = pHeight - sHeight; + } + + @Override + public void update() { + locY += acceleration; + if(locY >= 0) + locY = 0; + } +} diff --git a/src/com/sagi/dayan/Games/Elements/DemoSprite.java b/src/com/sagi/dayan/Games/Elements/DemoSprite.java new file mode 100644 index 0000000..08c760b --- /dev/null +++ b/src/com/sagi/dayan/Games/Elements/DemoSprite.java @@ -0,0 +1,64 @@ +package com.sagi.dayan.Games.Elements; + +import java.util.Random; + +/** + * Created by sagi on 2/10/16. + */ +public class DemoSprite extends Sprite { + private final int STOP=0, UP=1, DOWN=-1, TURN_SPEED=10; + private final double MAX_SPEED = 6, SLOWING_FACTOR = 0.1; + Random r; + private double selfAccel; + private int direction, turnDirection; + int counter = 0; + public DemoSprite(int x, int y, int w, int h, int acc, String imgName, double angle, int sWidth, int sHeight) { + super(x, y, w, h, acc, imgName, angle, sWidth, sHeight); + selfRotationSpeed = 5; + direction = STOP; + turnDirection = STOP; + selfAccel = acceleration; + setScreenLoop(true); + + } + + @Override + public void update() { + setSpeed(); + this.angle+=TURN_SPEED*turnDirection; + locX += selfAccel * Math.cos(Math.toRadians(angle)); + locY -= selfAccel * (-1 * Math.sin(Math.toRadians(angle))); + System.out.println("locX: " + locX + "\tlocY: "+locY); + } + + private void setSpeed(){ + if (direction == UP && !(selfAccel > MAX_SPEED)){ + selfAccel+=SLOWING_FACTOR*2; + } + else if (direction == DOWN && (selfAccel > MAX_SPEED*(-1))){ + selfAccel-=SLOWING_FACTOR*2; + } + else { //slowing down + if (selfAccel > 0) { + selfAccel -= SLOWING_FACTOR; + if (selfAccel < 0) { + selfAccel = 0; + } + } + if (selfAccel < 0) { + selfAccel += SLOWING_FACTOR; + if (selfAccel > 0) { + selfAccel = 0; + } + } + } + } + + public void setDirection(int direction) { + this.direction = direction; + } + + public void turnShip(int direction){ + turnDirection=direction; + } +} diff --git a/src/com/sagi/dayan/Games/Elements/EnemyShip.java b/src/com/sagi/dayan/Games/Elements/EnemyShip.java new file mode 100644 index 0000000..3868b77 --- /dev/null +++ b/src/com/sagi/dayan/Games/Elements/EnemyShip.java @@ -0,0 +1,35 @@ +package com.sagi.dayan.Games.Elements; + +import javax.swing.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + + +/** + * Created by sagi on 2/20/16. + */ +public class EnemyShip extends AnimatedSprite { + Timer t; + public EnemyShip(int x, int y, int w, int h, int acc, String imgName, double angle, int sWidth, int sHeight, ActionListener timerListener) { + super(x, y, w, h, acc, imgName, angle, sWidth, sHeight); + + t = new Timer(1000,timerListener); + + } + + @Override + protected void initFirstAnimation(String spriteSheet) { + animations.add(new Animation("P1Laser.png", 4, 500)); + } + + @Override + public void update() { + locX = 200; + locY += acceleration; + } + + + + + +} diff --git a/src/com/sagi/dayan/Games/Elements/MenuBoxSprite.java b/src/com/sagi/dayan/Games/Elements/MenuBoxSprite.java new file mode 100644 index 0000000..2cb72a2 --- /dev/null +++ b/src/com/sagi/dayan/Games/Elements/MenuBoxSprite.java @@ -0,0 +1,20 @@ +package com.sagi.dayan.Games.Elements; + +/** + * Created by sagi on 2/24/16. + */ +public class MenuBoxSprite extends AnimatedSprite { + public MenuBoxSprite(int x, int y, int w, int h, int acc, String imgName, double angle, int sWidth, int sHeight) { + super(x, y, w, h, acc, imgName, angle, sWidth, sHeight); + } + + @Override + protected void initFirstAnimation(String spriteSheet) { + animations.add(new Animation("menuBox.png", 15, 150)); + } + + @Override + public void update() { + + } +} diff --git a/src/com/sagi/dayan/Games/Elements/Missile.java b/src/com/sagi/dayan/Games/Elements/Missile.java new file mode 100644 index 0000000..2bb3a5d --- /dev/null +++ b/src/com/sagi/dayan/Games/Elements/Missile.java @@ -0,0 +1,22 @@ +package com.sagi.dayan.Games.Elements; + +/** + * Created by sagi on 2/20/16. + */ +public class Missile extends AnimatedSprite { + + + public Missile(int x, int y, int acc, String imgName) { + super(x, y, 0, 0, acc, imgName, 0, 15, 15); + } + + @Override + protected void initFirstAnimation(String spriteSheet) { + animations.add(new Animation("P1Laser.png", 4, 500)); + } + + @Override + public void update() { + locY -= acceleration; + } +} diff --git a/src/com/sagi/dayan/Games/Elements/Player.java b/src/com/sagi/dayan/Games/Elements/Player.java new file mode 100644 index 0000000..4f7ec5d --- /dev/null +++ b/src/com/sagi/dayan/Games/Elements/Player.java @@ -0,0 +1,91 @@ +package com.sagi.dayan.Games.Elements; + +/** + * Created by sagi on 2/20/16. + */ +public class Player extends AnimatedSprite { + private final int NORMAL_ANIMATION = 0, RIGHT_ANIMATION = 1, LEFT_ANIMATION = 2, PADDING_BOTTOM = 35; + private int hDirection = 0, vDirection = 0; + private String imagePrefix; + private boolean ableToFire; + private int fireDelay; + private long lastFired; + + + public Player(int x, int y, int w, int h, int acc, String imgName, double angle, int sWidth, int sHeight, String imagePrefix) { + super(x, y, w, h, acc, imgName, angle, sWidth, sHeight); + this.imagePrefix = imagePrefix; + initFirstAnimation(""); + this.ableToFire = true; + fireDelay = 100; + lastFired = System.currentTimeMillis(); + } + + @Override + protected void initFirstAnimation(String spriteSheet) { + if(imagePrefix == null) + return; + System.out.println(imagePrefix); + animations.add(new Animation(imagePrefix+"StraighSheet.png", 7, 200)); + animations.add(new Animation(imagePrefix+"RightSheet.png", 7, 200)); + animations.add(new Animation(imagePrefix+"LeftSheet.png", 7, 200)); + } + + @Override + public void update() { + long now = System.currentTimeMillis(); + if(now - lastFired >= fireDelay){ + ableToFire = true; + }else{ + ableToFire = false; + } + locX += vDirection * acceleration; + locY -= hDirection * acceleration; + if(locX < 0) + locX = 0; + else if(locX > pWidth - animations.get(currentAnimation).getCurrentFrame().getWidth()){ + locX = pWidth - animations.get(currentAnimation).getCurrentFrame().getWidth(); + } + + if(locY < 0) + locY = 0; + else if(locY > pHeight - animations.get(currentAnimation).getCurrentFrame().getHeight() - PADDING_BOTTOM){ + locY = pHeight - animations.get(currentAnimation).getCurrentFrame().getHeight() - PADDING_BOTTOM; + } + + + } + + public void sethDirection(int direction) { + this.hDirection = direction; + } + + public void setvDirection(int direction) { + this.vDirection = direction; + if(direction != NORMAL_ANIMATION){ + currentAnimation = (direction == 1) ? RIGHT_ANIMATION : LEFT_ANIMATION; + }else{ + currentAnimation = 0; + } + } + + public boolean isAbleToFire() { + return ableToFire; + } + + public void setAbleToFire(boolean ableToFire) { + this.ableToFire = ableToFire; + } + + public int getFireDelay() { + return fireDelay; + } + + public void setFireDelay(int fireDelay) { + this.fireDelay = fireDelay; + } + + public void updateFireTime(){ + lastFired = System.currentTimeMillis(); + } +} diff --git a/src/com/sagi/dayan/Games/Elements/Sprite.java b/src/com/sagi/dayan/Games/Elements/Sprite.java new file mode 100644 index 0000000..0f336ba --- /dev/null +++ b/src/com/sagi/dayan/Games/Elements/Sprite.java @@ -0,0 +1,261 @@ +package com.sagi.dayan.Games.Elements; + + +import javax.imageio.ImageIO; +import javax.swing.*; +import java.awt.*; +import java.awt.image.BufferedImage; +import java.io.IOException; +import java.net.URL; +import java.util.Vector; + + +public abstract class Sprite { + protected BufferedImage bImage; + protected int imageWidth, imageHeight; // image dimensions + protected URL imagePath; + protected int locX, locY; + protected int acceleration; + protected int pWidth, pHeight; // panel's dimensions + protected int sWidth, sHeight; + protected int selfRotationSpeed; + protected double angle; + protected boolean screenLoop = false; + + + + + public Sprite(int x, int y, int w, int h, int acc, String imgName, double angle, int sWidth, int sHeight) { + this.imagePath = getClass().getResource("/com/sagi/dayan/Games/Images/" + imgName); + this.sWidth = sWidth; + this.sHeight = sHeight; + locX = x; + locY = y; + acceleration = acc; + pWidth = w; + pHeight = h; + this.angle = angle; + + //load image from source files + try { + bImage = ImageIO.read(imagePath); + } catch (IOException pin) { + pin.printStackTrace(); + bImage = null; + } + +// setImageDimensions(); + } + + + /* + * resizes image to a set size + */ + protected void setImageDimensions() { + Image tmp = bImage.getScaledInstance(sWidth, sHeight, Image.SCALE_SMOOTH); + BufferedImage bi = new BufferedImage(sWidth, sHeight, BufferedImage.TYPE_INT_ARGB); + + Graphics2D g2d = bi.createGraphics(); + g2d.drawImage(tmp, 0, 0, null); + g2d.dispose(); + bImage = bi; + } + + /** + * Abstract method to update sprite. + */ + public abstract void update(); + + /** + * returns sprite x position + * + * @return double + */ + public double getLocX() { + return locX; + } + + public void setLocX(int locX) { + this.locX = locX; + } + + public void setLocY(int locY) { + this.locY = locY; + } + + /** + * returns sprite y position + * + * @return double + */ + public double getLocY() { + return locY; + } + + /** + * returns sprite image width + * + * @return int + */ + public int getSWidth() { + return sWidth; + } + + /** + * returns sprite image height + * + * @return int + */ + public int getsHeight() { + return sHeight; + } + + /** + * returns sprite acceleration + * + * @return int + */ + public int getAcceleration() { + return acceleration; + } + + /** + * returns sprite size + * + * @return int + */ + public BufferedImage getbImage() { + return bImage; + } + + /** + * returns image width + * + * @return int + */ + public int getImageWidth() { + return imageWidth; + } + + /** + * returns image height + * + * @return int + */ + public int getImageHeight() { + return imageHeight; + } + + /** + * returns sprite angle + * + * @return double + */ + public double getAngle() { + return angle; + } + + public int getCenterX() {return locX + (sWidth / 2);} + public int getCenterY() {return locY + (sHeight / 2);} + + + /** + * returns shape location and dimensions as a Rectangle. + * + * @return Rectangle + */ + public Rectangle getBounds() { + return new Rectangle((int) locX, (int) locY, sWidth, sHeight); + } + + public boolean isScreenLoop() { + return screenLoop; + } + + public void setScreenLoop(boolean screenLoop) { + this.screenLoop = screenLoop; + } + + + /** + * its not a bug it's a feature. actually it just moves a shape that goes beyond the screen to the other side. + */ + protected void outOfScreeFix(){ + /** + * X: Left Edge + */ + if(locX < 0 - sWidth) + locX = pWidth + locX; + /** + * X: Right Edge + */ + else if (locX > pWidth + sWidth) + locX = Math.abs(pWidth - (locX + sWidth)) - sWidth; + + /** + * Y: Top Edge + */ + if(locY < 0 - sHeight) + locY = pHeight + locY; + /** + * Y: Bottom Edge + */ + else if(locY > pHeight+sHeight) + locY = Math.abs(pHeight - (locY + sHeight)) - sHeight; + } + + protected void drawScreenLoopFix(Graphics g, JPanel p) { + Graphics2D g2d = (Graphics2D)g; + + /** + * Left Edge + */ + if (locX < 0) { + g2d.rotate(Math.toRadians(angle), pWidth + locX + (bImage.getWidth() / 2), locY + (bImage.getHeight() / 2)); + g.drawImage(bImage, pWidth + locX, locY, p); + g2d.rotate(-1 * Math.toRadians(angle), pWidth + locX + (bImage.getWidth() / 2), locY + (bImage.getHeight() / 2)); + } + + /** + * Right Edge + */ + if (locX + sWidth > pWidth ) { + g2d.rotate(Math.toRadians(angle), Math.abs(pWidth - (locX + sWidth)) - sWidth + (bImage.getWidth() / 2), locY + (bImage.getHeight() / 2)); + g.drawImage(bImage, Math.abs(pWidth - (locX + sWidth)) - sWidth, locY, p); + g2d.rotate(-1 * Math.toRadians(angle), Math.abs(pWidth - (locX + sWidth)) - sWidth + (bImage.getWidth() / 2), locY + (bImage.getHeight() / 2)); + } + /** + * Top Edge + */ + if (locY < 0) { + g2d.rotate(Math.toRadians(angle), locX + (bImage.getWidth() / 2), pHeight + locY + (bImage.getHeight() / 2)); + g.drawImage(bImage, locX , pHeight + locY, p); + g2d.rotate(-1 * Math.toRadians(angle), locX + (bImage.getWidth() / 2), pHeight + locY + (bImage.getHeight() / 2)); + } + /** + * Bottom Edge + */ + if ( pHeight < locY + sHeight) { + g2d.rotate(Math.toRadians(angle), locX + (bImage.getWidth() / 2), Math.abs(pHeight - (locY + sHeight)) - sHeight+ (bImage.getHeight() / 2)); + g.drawImage(bImage, locX , Math.abs(pHeight - (locY + sHeight)) - sHeight, p); + g2d.rotate(-1 * Math.toRadians(angle), locX + (bImage.getWidth() / 2), Math.abs(pHeight - (locY + sHeight)) - sHeight + (bImage.getHeight() / 2)); + } + } + + /** + * + * + * @param g + */ + public void drawSprite(Graphics g, JPanel p) { + Graphics2D g2d = (Graphics2D) g; + g2d.rotate(Math.toRadians(angle), locX + (bImage.getWidth() / 2), locY + (bImage.getHeight() / 2)); + g.drawImage(bImage, locX, locY, p); + g2d.rotate(-1 * Math.toRadians(angle), locX + (bImage.getWidth() / 2), locY + (bImage.getHeight() / 2)); + if(screenLoop) { + outOfScreeFix(); + drawScreenLoopFix(g, p); + } + } + +} \ No newline at end of file diff --git a/src/com/sagi/dayan/Games/Engine/CollisionUtil.java b/src/com/sagi/dayan/Games/Engine/CollisionUtil.java new file mode 100644 index 0000000..f26f18f --- /dev/null +++ b/src/com/sagi/dayan/Games/Engine/CollisionUtil.java @@ -0,0 +1,109 @@ +package com.sagi.dayan.Games.Engine; + + + + +/** + * Created by sagi on 12/19/15. + */ + +import com.sagi.dayan.Games.Elements.Sprite; + +import java.awt.*; +import java.awt.image.PixelGrabber; +public class CollisionUtil { + + /** + * Checks if a Sprite is colliding with another Sprite. + * @param otherSprite The Sprite to check a collission with. + * @param thisSprite another sprite + * @return true if the Sprites collide, otherwise false. + */ + public static boolean collidesWith(Sprite thisSprite, Sprite otherSprite) { + boolean isColliding=false; + + Rectangle r1 = thisSprite.getBounds(); + Rectangle r2 = otherSprite.getBounds(); + + r1.intersection(r2); + + if(intersection(r1, r2)) { + isColliding = pixelPerfectCollision(thisSprite, otherSprite, r1, r2); + } + return isColliding; + } + + private static boolean intersection(Rectangle r, Rectangle d) { + int rect1x = r.x; + int rect1y = r.y; + int rect1w = r.width; + int rect1h = r.height; + + int rect2x = d.x; + int rect2y = d.y; + int rect2w = d.width; + int rect2h = d.height; + + return (rect1x + rect1w >= rect2x && + rect1y + rect1h >= rect2y && + rect1x <= rect2x + rect2w && + rect1y <= rect2y + rect2h); + } + + + /* + * pixelPerfectCollision(); first determines the area where the sprites collides + * AKA the collision-rectangle. It then grabs the pixels from both sprites + * which are inside the rectangle. It then checks every pixel from the arrays + * given by grabPixels();, and if 2 pixels at the same position are opaque, + * (alpha value over 0) it will return true. Otherwise it will return false. + */ + private static boolean pixelPerfectCollision(Sprite sprite1,Sprite sprite2, Rectangle r1, Rectangle r2) { + /* + * Get the X-values and Y-values for the two coordinates where the sprites collide + */ + + int cornerTopX = (r1.x>r2.x)?r1.x:r2.x; + int cornerBottomX = ((r1.x+r1.width) < (r2.x+r2.width))?(r1.x+r1.width):(r2.x+r2.width); + + int cornerTopY = (r1.y>r2.y)?r1.y:r2.y; + int cornerBottomY = ((r1.y+r1.height) < (r2.y+r2.height))?(r1.y+r1.height):(r2.y+r2.height); + + //Determine the width and height of the collision rectangle + int width=cornerBottomX-cornerTopX; + int height=cornerBottomY-cornerTopY; + + //Create arrays to hold the pixels + int[] pixels1 = new int[width*height]; + int[] pixels2 = new int[width*height]; + + //Create the pixelgrabber and fill the arrays + PixelGrabber pg1 = new PixelGrabber(sprite1.getbImage(), cornerTopX-(int)sprite1.getLocX(), cornerTopY-(int)sprite1.getLocY(), width, height, pixels1, 0, width); + PixelGrabber pg2 = new PixelGrabber(sprite2.getbImage(), cornerTopX-(int)sprite2.getLocX(), cornerTopY-(int)sprite2.getLocY(), width, height, pixels2, 0, width); + + //Grab the pixels + try { + pg1.grabPixels(); + pg2.grabPixels(); + } catch (InterruptedException ex) { + //Logger.getLogger(Sprite.class.getName()).log(Level.SEVERE, null, ex); + } + + //Check if pixels at the same spot from both arrays are not transparent. + for(int i=0;i>> 24) & 0xff; + int a2 = (pixels2[i] >>> 24) & 0xff; + + /* Awesome, we found two pixels in the same spot that aren't + * completely transparent! Thus the sprites are colliding! + */ + if(a > 0 && a2 > 0) return true; + + } + + return false; + } + + + +} \ No newline at end of file diff --git a/src/com/sagi/dayan/Games/Engine/GameEngine.java b/src/com/sagi/dayan/Games/Engine/GameEngine.java new file mode 100644 index 0000000..ab99002 --- /dev/null +++ b/src/com/sagi/dayan/Games/Engine/GameEngine.java @@ -0,0 +1,163 @@ +package com.sagi.dayan.Games.Engine; + +/** + * Created by sagi on 2/8/16. + */ + +import com.sagi.dayan.Games.Elements.*; +import com.sagi.dayan.Games.Stage.*; +import com.sagi.dayan.Games.Utils.Utils; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.*; +import java.awt.image.BufferedImage; +import java.io.IOException; +import java.util.Random; +import java.util.Vector; + +/** + * Created by sagi on 12/18/15. + */ + + + +public class GameEngine { + public boolean gameOn , gameOver, isFirstGame; + private JFrame frame; + private int pWidth, pHeight, numOfPlayers; //panel dimensions + private Random r; + private Stage stage; + private Vector scenes; + private int currentScene; + public static final int PLAYER_WIDTH = 120, PLAYER_HEIGHT = 120; + public static final int UP=0,RIGHT=1,DOWN=2, LEFT=3, FIRE=4, SPECIAL=5; + + private int[] p1Controlles = {KeyEvent.VK_UP, KeyEvent.VK_RIGHT, KeyEvent.VK_DOWN, KeyEvent.VK_LEFT, KeyEvent.VK_K}; + private int[] p2Controlles = {KeyEvent.VK_W, KeyEvent.VK_D, KeyEvent.VK_S, KeyEvent.VK_A, KeyEvent.VK_SHIFT}; + + private Font gameFont; + + public GameEngine(int width, int height, Stage stage){ + this.currentScene = 0; + this.isFirstGame = true; + this.gameOver = true; + this.pWidth = width; + this.pHeight = height; + this.scenes = new Vector<>(); + this.stage = stage; +// scenes.add(new FirstStage(width, height, 2)); // Need to be a menu Scene + scenes.add(new MainMenuScene(width, height, this)); + stage.addKeyListener(scenes.get(currentScene)); + stage.addMouseListener(scenes.get(currentScene)); + r = new Random(); + try{ + gameFont = Font.createFont(Font.TRUETYPE_FONT,Utils.getFontStream("transformers.ttf")); + } catch (FontFormatException e) { + e.printStackTrace(); + gameFont = null; + } catch (IOException e) { + e.printStackTrace(); + gameFont = null; + } + startNewGame(); + } + + + + /** + * initialize and reset vars and timers to "new game" configuration. + */ + private void startNewGame(){ + this.gameOn = true; + initGame(); + } + + /** + * Setup all actors in the game to a new game - reset timer + */ + private void initGame(){ + + + + } + + + + + + /** + * returns gameOver flag + * @return + * boolean + */ + public boolean isGameOver(){ + return this.gameOver; + } + + + + + + /** + * Update all sprites, including collision handling. + */ + public void update(){ + scenes.get(currentScene).update(); + } + + public void render(JPanel p) { + scenes.get(currentScene).render(p); + } + + public BufferedImage getScene() { + return scenes.get(currentScene).getSceneImage(); + } + + private void changeScene(int index) { + if (index >= scenes.size()){ + throw new IllegalArgumentException("Invalid Index. scenes size: "+scenes.size()); + } + stage.removeKeyListener(scenes.get(currentScene)); + stage.removeMouseListener(scenes.get(currentScene)); + currentScene = index; + stage.addKeyListener(scenes.get(currentScene)); + stage.addMouseListener(scenes.get(currentScene)); + } + + public void startGame(int numOfPlayers){ + this.numOfPlayers = numOfPlayers; + scenes.add(new FirstStage(pWidth, pHeight, numOfPlayers, this, "-= STAGE 1.0 =-")); + changeScene(currentScene+1); + } + + + public void goToSettings() { + scenes.add(new SettingsMenuScene(pWidth, pHeight, this)); + changeScene(currentScene+1); + } + + public void goToMainMenu() { + + changeScene(0); + for(int i = scenes.size() -1 ; i > 0 ; i--){ + scenes.remove(i); + } + } + + public int getScenesSize(){ + return scenes.size(); + } + + public int[] getP1Controlles(){ + return p1Controlles; + } + + public int[] getP2Controlles(){ + return p2Controlles; + } + + public Font getGameFont() { + return gameFont; + } +} \ No newline at end of file diff --git a/src/com/sagi/dayan/Games/Fonts/transformers.ttf b/src/com/sagi/dayan/Games/Fonts/transformers.ttf new file mode 100644 index 0000000..326e0a1 Binary files /dev/null and b/src/com/sagi/dayan/Games/Fonts/transformers.ttf differ diff --git a/src/com/sagi/dayan/Games/Graphics/Settigns menu.xcf b/src/com/sagi/dayan/Games/Graphics/Settigns menu.xcf new file mode 100644 index 0000000..7400c4d Binary files /dev/null and b/src/com/sagi/dayan/Games/Graphics/Settigns menu.xcf differ diff --git a/src/com/sagi/dayan/Games/Graphics/main mwnu.xcf b/src/com/sagi/dayan/Games/Graphics/main mwnu.xcf new file mode 100644 index 0000000..9b20fd6 Binary files /dev/null and b/src/com/sagi/dayan/Games/Graphics/main mwnu.xcf differ diff --git a/src/com/sagi/dayan/Games/Images/L1-BG.jpg b/src/com/sagi/dayan/Games/Images/L1-BG.jpg new file mode 100644 index 0000000..c561f09 Binary files /dev/null and b/src/com/sagi/dayan/Games/Images/L1-BG.jpg differ diff --git a/src/com/sagi/dayan/Games/Images/L1-ES1.png b/src/com/sagi/dayan/Games/Images/L1-ES1.png new file mode 100644 index 0000000..08d83aa Binary files /dev/null and b/src/com/sagi/dayan/Games/Images/L1-ES1.png differ diff --git a/src/com/sagi/dayan/Games/Images/P1Laser.png b/src/com/sagi/dayan/Games/Images/P1Laser.png new file mode 100644 index 0000000..187c561 Binary files /dev/null and b/src/com/sagi/dayan/Games/Images/P1Laser.png differ diff --git a/src/com/sagi/dayan/Games/Images/P1LeftSheet.png b/src/com/sagi/dayan/Games/Images/P1LeftSheet.png new file mode 100644 index 0000000..9c6eb61 Binary files /dev/null and b/src/com/sagi/dayan/Games/Images/P1LeftSheet.png differ diff --git a/src/com/sagi/dayan/Games/Images/P1RightSheet.png b/src/com/sagi/dayan/Games/Images/P1RightSheet.png new file mode 100644 index 0000000..c813798 Binary files /dev/null and b/src/com/sagi/dayan/Games/Images/P1RightSheet.png differ diff --git a/src/com/sagi/dayan/Games/Images/P1StraighSheet.png b/src/com/sagi/dayan/Games/Images/P1StraighSheet.png new file mode 100644 index 0000000..6a51824 Binary files /dev/null and b/src/com/sagi/dayan/Games/Images/P1StraighSheet.png differ diff --git a/src/com/sagi/dayan/Games/Images/P2LeftSheet.png b/src/com/sagi/dayan/Games/Images/P2LeftSheet.png new file mode 100644 index 0000000..2e29389 Binary files /dev/null and b/src/com/sagi/dayan/Games/Images/P2LeftSheet.png differ diff --git a/src/com/sagi/dayan/Games/Images/P2RightSheet.png b/src/com/sagi/dayan/Games/Images/P2RightSheet.png new file mode 100644 index 0000000..13abc83 Binary files /dev/null and b/src/com/sagi/dayan/Games/Images/P2RightSheet.png differ diff --git a/src/com/sagi/dayan/Games/Images/P2StraighSheet.png b/src/com/sagi/dayan/Games/Images/P2StraighSheet.png new file mode 100644 index 0000000..212ccf0 Binary files /dev/null and b/src/com/sagi/dayan/Games/Images/P2StraighSheet.png differ diff --git a/src/com/sagi/dayan/Games/Images/Settigns_menu.jpg b/src/com/sagi/dayan/Games/Images/Settigns_menu.jpg new file mode 100644 index 0000000..7091b57 Binary files /dev/null and b/src/com/sagi/dayan/Games/Images/Settigns_menu.jpg differ diff --git a/src/com/sagi/dayan/Games/Images/animatedSample.png b/src/com/sagi/dayan/Games/Images/animatedSample.png new file mode 100644 index 0000000..c7e05fa Binary files /dev/null and b/src/com/sagi/dayan/Games/Images/animatedSample.png differ diff --git a/src/com/sagi/dayan/Games/Images/animatedSample2.png b/src/com/sagi/dayan/Games/Images/animatedSample2.png new file mode 100644 index 0000000..2cf5e3c Binary files /dev/null and b/src/com/sagi/dayan/Games/Images/animatedSample2.png differ diff --git a/src/com/sagi/dayan/Games/Images/emptyImage.png b/src/com/sagi/dayan/Games/Images/emptyImage.png new file mode 100644 index 0000000..e6017fd Binary files /dev/null and b/src/com/sagi/dayan/Games/Images/emptyImage.png differ diff --git a/src/com/sagi/dayan/Games/Images/menu.jpg b/src/com/sagi/dayan/Games/Images/menu.jpg new file mode 100644 index 0000000..58ab16f Binary files /dev/null and b/src/com/sagi/dayan/Games/Images/menu.jpg differ diff --git a/src/com/sagi/dayan/Games/Images/menu0.png b/src/com/sagi/dayan/Games/Images/menu0.png new file mode 100644 index 0000000..a9675c3 Binary files /dev/null and b/src/com/sagi/dayan/Games/Images/menu0.png differ diff --git a/src/com/sagi/dayan/Games/Images/menuBack.jpg b/src/com/sagi/dayan/Games/Images/menuBack.jpg new file mode 100644 index 0000000..272a343 Binary files /dev/null and b/src/com/sagi/dayan/Games/Images/menuBack.jpg differ diff --git a/src/com/sagi/dayan/Games/Images/menuBox.png b/src/com/sagi/dayan/Games/Images/menuBox.png new file mode 100644 index 0000000..df83ad8 Binary files /dev/null and b/src/com/sagi/dayan/Games/Images/menuBox.png differ diff --git a/src/com/sagi/dayan/Games/Images/ship2.png b/src/com/sagi/dayan/Games/Images/ship2.png new file mode 100644 index 0000000..742306c Binary files /dev/null and b/src/com/sagi/dayan/Games/Images/ship2.png differ diff --git a/src/com/sagi/dayan/Games/Main.java b/src/com/sagi/dayan/Games/Main.java new file mode 100644 index 0000000..5185d3a --- /dev/null +++ b/src/com/sagi/dayan/Games/Main.java @@ -0,0 +1,36 @@ +package com.sagi.dayan.Games; + +import com.sagi.dayan.Games.Engine.GameEngine; +import com.sagi.dayan.Games.Stage.Stage; +import com.sagi.dayan.Games.Utils.Utils; + +import javax.swing.*; +import java.awt.*; +import java.io.File; +import java.io.IOException; + + +/** + * Created by sagi on 2/8/16. + */ + + +public class Main { + + public static final int WIDTH = 1000, HEIGHT = 1000; + + public static void main(String[] args) { + JFrame frame = new JFrame("Game"); + frame.setSize(WIDTH, HEIGHT); + frame.setResizable(false); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + frame.add(new Stage(WIDTH, HEIGHT)); + frame.setVisible(true); + frame.setBackground(Color.BLACK); + System.out.println(WIDTH + "\t" + (HEIGHT)); + System.out.println("========================================="); + } + + + +} diff --git a/src/com/sagi/dayan/Games/Sounds/intro.mp3 b/src/com/sagi/dayan/Games/Sounds/intro.mp3 new file mode 100644 index 0000000..a13f187 Binary files /dev/null and b/src/com/sagi/dayan/Games/Sounds/intro.mp3 differ diff --git a/src/com/sagi/dayan/Games/Sounds/intro.wav b/src/com/sagi/dayan/Games/Sounds/intro.wav new file mode 100644 index 0000000..4edef53 Binary files /dev/null and b/src/com/sagi/dayan/Games/Sounds/intro.wav differ diff --git a/src/com/sagi/dayan/Games/Sounds/introBackup.wav b/src/com/sagi/dayan/Games/Sounds/introBackup.wav new file mode 100644 index 0000000..c1ae5d7 Binary files /dev/null and b/src/com/sagi/dayan/Games/Sounds/introBackup.wav differ diff --git a/src/com/sagi/dayan/Games/Sounds/jetSound.wav b/src/com/sagi/dayan/Games/Sounds/jetSound.wav new file mode 100644 index 0000000..990e7fe Binary files /dev/null and b/src/com/sagi/dayan/Games/Sounds/jetSound.wav differ diff --git a/src/com/sagi/dayan/Games/Sounds/menuItem.wav b/src/com/sagi/dayan/Games/Sounds/menuItem.wav new file mode 100644 index 0000000..0788a4d Binary files /dev/null and b/src/com/sagi/dayan/Games/Sounds/menuItem.wav differ diff --git a/src/com/sagi/dayan/Games/Sounds/menuSelect.wav b/src/com/sagi/dayan/Games/Sounds/menuSelect.wav new file mode 100644 index 0000000..73cc536 Binary files /dev/null and b/src/com/sagi/dayan/Games/Sounds/menuSelect.wav differ diff --git a/src/com/sagi/dayan/Games/Stage/FirstStage.java b/src/com/sagi/dayan/Games/Stage/FirstStage.java new file mode 100644 index 0000000..6d129aa --- /dev/null +++ b/src/com/sagi/dayan/Games/Stage/FirstStage.java @@ -0,0 +1,274 @@ +package com.sagi.dayan.Games.Stage; + +import com.sagi.dayan.Games.Elements.Background; +import com.sagi.dayan.Games.Elements.EnemyShip; +import com.sagi.dayan.Games.Elements.Missile; +import com.sagi.dayan.Games.Elements.Player; +import com.sagi.dayan.Games.Engine.GameEngine; +import com.sagi.dayan.Games.Utils.Utils; + +import javax.swing.*; +import javax.swing.Timer; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.KeyEvent; +import java.awt.image.BufferedImage; +import java.io.IOException; +import java.util.*; + +/** + * Created by sagi on 2/20/16. + */ +public class FirstStage extends Scene { + protected Vector players; + protected int p1Speed = 10; + protected Vector missiles; + protected Background bg; + protected Timer enemyWaveT, enemyT; + protected Vector enemies; + protected int[] yAxisStartingAnimation; + protected int startingAnimationIndex; + protected boolean isStarted; + protected int numOfPlayers; + protected Map keys; + protected String title; + protected JLabel stageTitle; + + + + + public FirstStage(int width, int height, int numOfPlayers, GameEngine engine, String stageTitle){ + super(width, height, engine); + players = new Vector<>(); + missiles = new Vector<>(); + isStarted = false; + keys = new HashMap<>(); + yAxisStartingAnimation = new int[]{height + (5*GameEngine.PLAYER_HEIGHT) , height - (4*GameEngine.PLAYER_HEIGHT) , height - (GameEngine.PLAYER_HEIGHT + 15)}; + startingAnimationIndex = 0; + bg = new Background(0,0,width,height, 1, "L1-BG.jpg", 0,1000, 4760); + this.numOfPlayers = numOfPlayers; + this.title = stageTitle; + this.stageTitle = new JLabel(this.title); + + if(numOfPlayers == 1) { + players.add(new Player((width / 2) + (GameEngine.PLAYER_WIDTH / 2), yAxisStartingAnimation[startingAnimationIndex], width, height, p1Speed, "emptyImage.png", 0, GameEngine.PLAYER_WIDTH, GameEngine.PLAYER_HEIGHT, "P1")); + }else{ + players.add(new Player((width / 2) + (GameEngine.PLAYER_WIDTH / 2) + GameEngine.PLAYER_WIDTH, yAxisStartingAnimation[startingAnimationIndex], width, height, p1Speed, "emptyImage.png", 0, GameEngine.PLAYER_WIDTH, GameEngine.PLAYER_HEIGHT, "P1")); + players.add(new Player((width / 2) + (GameEngine.PLAYER_WIDTH / 2) - GameEngine.PLAYER_WIDTH*3, yAxisStartingAnimation[startingAnimationIndex], width, height, p1Speed, "emptyImage.png", 0, GameEngine.PLAYER_WIDTH, GameEngine.PLAYER_HEIGHT, "P2")); + + } + + setupKeys(); + enemies = new Vector<>(); + enemyWaveT = new Timer(10000, new enemyWaveLaunch()); + enemyT = new Timer(10000, new enemyLaunch()); + enemyWaveT.start(); + + Utils.playSound("jetSound.wav"); + } + + private void setupKeys() { + int[] p1 = engine.getP1Controlles(); + for(int i = 0 ; i < p1.length ; i++){ + keys.put(p1[i], false); + } + if(numOfPlayers > 1){ + int[] p2 = engine.getP2Controlles(); + for(int i = 0 ; i < p1.length ; i++){ + keys.put(p2[i], false); + } + } + } + + @Override + public void update() { + + bg.update(); + movePlayers(); + + if(startingAnimationIndex < 3 && !isStarted){ + if(startingAnimationIndex == 0){ + startingAnimationIndex++; + } + if(players.get(0).getLocY() > yAxisStartingAnimation[startingAnimationIndex] && startingAnimationIndex == 1){ + for(int i = 0 ; i < players.size() ; i++){ + players.get(i).setLocY((int)players.get(i).getLocY() - (p1Speed)); +// players.get(i).update(); + } + if(players.get(0).getLocY() <= yAxisStartingAnimation[startingAnimationIndex]){ + startingAnimationIndex++; + } + }else{ + + for(int i = 0 ; i < players.size() ; i++){ + players.get(i).setLocY((int)players.get(i).getLocY() + (p1Speed - 5)); +// players.get(i).update(); + } + if(players.get(0).getLocY() >= yAxisStartingAnimation[startingAnimationIndex]){ + startingAnimationIndex++; + } + } + }else{ + + isStarted = true; + for(int i = 0 ; i < players.size() ; i++){ + players.get(i).update(); + } + + for(int i = 0 ; i < missiles.size() ; i++){ + missiles.get(i).update(); + } + + for(int i = 0 ; i < enemies.size() ; i++){ + enemies.get(i).update(); + } + } + + + } + + private void movePlayers() { + /** + * Player 1 Movement: + */ + if(keys.get(engine.getP1Controlles()[GameEngine.UP]) ){ //UP + players.get(0).sethDirection(1); + } + if(keys.get(engine.getP1Controlles()[GameEngine.DOWN])){ // DOWN + players.get(0).sethDirection(-1); + } + if(!keys.get(engine.getP1Controlles()[GameEngine.UP]) && !keys.get(engine.getP1Controlles()[GameEngine.DOWN])){ // Not up Or Down + players.get(0).sethDirection(0); + } + if(keys.get(engine.getP1Controlles()[GameEngine.LEFT])) { // Left + players.get(0).setvDirection(-1); + } + if(keys.get(engine.getP1Controlles()[GameEngine.RIGHT])) { // Right + players.get(0).setvDirection(1); + } + if(!keys.get(engine.getP1Controlles()[GameEngine.LEFT]) && !keys.get(engine.getP1Controlles()[GameEngine.RIGHT])){ // Not right or left + players.get(0).setvDirection(0); + } + if(keys.get(engine.getP1Controlles()[GameEngine.FIRE]) ){ + if(players.get(0).isAbleToFire()){ + missiles.add(new Missile(players.get(0).getCenterX() - 3, (int)players.get(0).getLocY(), players.get(0).getAcceleration() + 3, "P1Laser.png")); + players.get(0).updateFireTime(); + } + } + + /** + * Player 2 Movement + */ + if(numOfPlayers > 1){ + if(keys.get(engine.getP2Controlles()[GameEngine.UP]) ){ //UP + players.get(1).sethDirection(1); + } + if(keys.get(engine.getP2Controlles()[GameEngine.DOWN])){ // DOWN + players.get(1).sethDirection(-1); + } + if(!keys.get(engine.getP2Controlles()[GameEngine.UP]) && !keys.get(engine.getP2Controlles()[GameEngine.DOWN])){ // Not up Or Down + players.get(1).sethDirection(0); + } + if(keys.get(engine.getP2Controlles()[GameEngine.LEFT])) { // Left + players.get(1).setvDirection(-1); + } + if(keys.get(engine.getP2Controlles()[GameEngine.RIGHT])) { // Right + players.get(1).setvDirection(1); + } + if(!keys.get(engine.getP2Controlles()[GameEngine.LEFT]) && !keys.get(engine.getP2Controlles()[GameEngine.RIGHT])){ // Not right or left + players.get(1).setvDirection(0); + } + if(keys.get(engine.getP2Controlles()[GameEngine.FIRE]) ){ + if(players.get(1).isAbleToFire()){ + missiles.add(new Missile(players.get(1).getCenterX() - 3, (int)players.get(1).getLocY(), players.get(1).getAcceleration() + 3, "P1Laser.png")); + players.get(1).updateFireTime(); + } + } + } + } + + @Override + public void render(JPanel p) { + sceneImage = new BufferedImage(this.stageWidth, this.stageHeight, Image.SCALE_FAST); + Graphics g = sceneImage.getGraphics(); + + bg.drawSprite(g, p); + Color c = g.getColor(); + if(!isStarted){ + Font f = engine.getGameFont(); + if(f == null) { + f = g.getFont(); + } + f = f.deriveFont(60F); + g.setColor(Color.DARK_GRAY); + g.setFont(f); + + + // Get the FontMetrics + FontMetrics metrics = g.getFontMetrics(f); + // Determine the X coordinate for the text + int x = (stageWidth - metrics.stringWidth(this.title)) / 2; + // Determine the Y coordinate for the text + int y = ((stageHeight - metrics.getHeight()) / 2) - metrics.getAscent(); + g.drawString(this.title, x, y); + g.setColor(c); + } + + + for(int i = 0 ; i < missiles.size() ; i++){ + missiles.get(i).drawSprite(g,p); + } + for(int i = 0 ; i < players.size() ; i++){ + players.get(i).drawSprite(g,p); + } + + for(int i = 0 ; i < enemies.size() ; i++){ + enemies.get(i).drawSprite(g,p); + } + } + + @Override + public void keyTyped(KeyEvent keyEvent) { + + } + + @Override + public void keyPressed(KeyEvent keyEvent) { + if(isStarted) + keys.put(keyEvent.getKeyCode(), true); + + } + + @Override + public void keyReleased(KeyEvent keyEvent) { + if(isStarted) + keys.put(keyEvent.getKeyCode(), false); + } + + private class fireTimer implements ActionListener { + + @Override + public void actionPerformed(ActionEvent actionEvent) { + missiles.add(new Missile(((EnemyShip)actionEvent.getSource()).getCenterX(), (int)((EnemyShip)actionEvent.getSource()).getLocY(), ((EnemyShip)actionEvent.getSource()).getAcceleration() + 3, "P1Laser.png")); + } + } + + private class enemyWaveLaunch implements ActionListener { + + @Override + public void actionPerformed(ActionEvent actionEvent) { + } + + + } + + private class enemyLaunch implements ActionListener { + + @Override + public void actionPerformed(ActionEvent actionEvent) { + enemies.add(new EnemyShip(0,0,0,0,3,"L1-ES1.png",0,15,15,new fireTimer())); + } + + } +} diff --git a/src/com/sagi/dayan/Games/Stage/MainMenuScene.java b/src/com/sagi/dayan/Games/Stage/MainMenuScene.java new file mode 100644 index 0000000..d34e9c2 --- /dev/null +++ b/src/com/sagi/dayan/Games/Stage/MainMenuScene.java @@ -0,0 +1,101 @@ +package com.sagi.dayan.Games.Stage; + +import com.sagi.dayan.Games.Elements.MenuBoxSprite; +import com.sagi.dayan.Games.Engine.GameEngine; +import com.sagi.dayan.Games.Utils.Utils; +import sun.audio.AudioPlayer; +import sun.audio.AudioStream; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.KeyEvent; +import java.awt.image.BufferedImage; +import java.io.*; + +/** + * Created by sagi on 2/24/16. + */ +public class MainMenuScene extends Scene { + + private MenuBoxSprite menuBox; + private int menuItem; + + + private final int MAX_ITEM_INDEX = 3, X_AXIS=560, ITEM_EXIT = 3, ITEM_SETTINGS = 2, ITEM_2P = 1, ITEM_1P = 0; + private int[] axis = {370, 480, 590, 700}; + + + + public MainMenuScene(int stageWidth, int stageHeight, GameEngine engine) { + super(stageWidth, stageHeight, engine); + menuItem = 0; + menuBox = new MenuBoxSprite(X_AXIS, axis[menuItem], stageWidth, stageHeight, 0, "menu.jpg", 0, 425, 110); //bImage is the background... not trivial + try { + AudioPlayer.player.start(new AudioStream(Utils.getSoundResourceAsStream("intro.wav"))); + } catch (IOException e) { + e.printStackTrace(); + } + } + + @Override + public void update() { + menuBox.setLocY(axis[menuItem]); + menuBox.update(); + + + } + + @Override + public void render(JPanel p) { + sceneImage = new BufferedImage(this.stageWidth, this.stageHeight, Image.SCALE_FAST); + Graphics g = sceneImage.getGraphics(); + g.drawImage(menuBox.getbImage(), 0, 0, p); + menuBox.drawSprite(g, p); + } + + @Override + public void keyTyped(KeyEvent keyEvent) { + + } + + @Override + public void keyPressed(KeyEvent keyEvent) { + switch (keyEvent.getKeyCode()){ + case KeyEvent.VK_UP: + if(menuItem == 0) + menuItem = MAX_ITEM_INDEX; + else + menuItem--; + Utils.playSound("menuSelect.wav"); + break; + case KeyEvent.VK_DOWN: + if(menuItem == MAX_ITEM_INDEX) + menuItem = 0; + else + menuItem++; + Utils.playSound("menuSelect.wav"); + break; + case KeyEvent.VK_ENTER: + switch(menuItem){ + case ITEM_1P: + case ITEM_2P: + Utils.playSound("menuItem.wav"); + engine.startGame(menuItem+1); + break; + case ITEM_SETTINGS: + Utils.playSound("menuItem.wav"); + engine.goToSettings(); + break; + case ITEM_EXIT: + System.exit(0); + break; + } + + } + } + + @Override + public void keyReleased(KeyEvent keyEvent) { + + } +} diff --git a/src/com/sagi/dayan/Games/Stage/SampleScene.java b/src/com/sagi/dayan/Games/Stage/SampleScene.java new file mode 100644 index 0000000..3fbefff --- /dev/null +++ b/src/com/sagi/dayan/Games/Stage/SampleScene.java @@ -0,0 +1,118 @@ +package com.sagi.dayan.Games.Stage; + +import com.sagi.dayan.Games.Elements.*; +import com.sagi.dayan.Games.Engine.GameEngine; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.KeyEvent; +import java.awt.event.MouseEvent; +import java.awt.image.BufferedImage; + +/** + * Created by sagi on 2/10/16. + */ +public class SampleScene extends Scene { + private final int STOP=0, UP=1, DOWN=-1, TURN_SPEED=10; + private DemoSprite sprite; + private AnimatedDemoSprite animated; + private int r = 0, g = 0, b = 0; + private boolean toWhite = true; + + public SampleScene(int width, int height, GameEngine engine){ + super(width, height, engine); +// sprite = new DemoSprite(50,50,width, height, 50); + animated = new AnimatedDemoSprite(width/2, height/2, width, height,5,"animatedSample.png", 0, 58,87); + } + + @Override + public void update() { + sprite.update(); + animated.update(); + } + + @Override + public void render(JPanel p) { + sceneImage = new BufferedImage(this.stageWidth, this.stageHeight, Image.SCALE_FAST); + Graphics g = sceneImage.getGraphics(); + g.setColor(getColor()); + g.fillRect(0,0,stageWidth, stageWidth); + sprite.drawSprite(g, p); + animated.drawSprite(g, p); + } + + + @Override + public void keyTyped(KeyEvent keyEvent) { + + } + + @Override + public void keyPressed(KeyEvent keyEvent) { + System.out.println("Pressed!"); + + if (keyEvent.getKeyCode() == keyEvent.VK_LEFT) { + sprite.turnShip(DOWN); + } + if (keyEvent.getKeyCode() == keyEvent.VK_RIGHT) { + sprite.turnShip(UP); + } + if (keyEvent.getKeyCode() == keyEvent.VK_UP) { + sprite.setDirection(UP); + } + if (keyEvent.getKeyCode() == keyEvent.VK_DOWN) { + sprite.setDirection(DOWN); + } + + } + + @Override + public void keyReleased(KeyEvent keyEvent) { + switch (keyEvent.getKeyCode()){ + case KeyEvent.VK_UP: + case KeyEvent.VK_DOWN: + sprite.setDirection(STOP); + break; + case KeyEvent.VK_RIGHT: + case KeyEvent.VK_LEFT: + sprite.turnShip(STOP); + break; +// case KeyEvent.VK_SPACE: +// laserAudioClip.stop(); +// break; + default: + break; + + } + } + + public void mousePressed(MouseEvent e){ + System.out.println("Mouse pressed"); + } + + private Color getColor() { + if(toWhite){ + if(r < 225) { + r++; + } else if (g < 225) { + g++; + } else if ( b < 225) { + b++; + }else if (r == 225 && g ==225 && b == 225){ + toWhite = false; + } + } else { + if(b > 0) { + b--; + } else if (g > 0) { + g--; + } else if ( r > 0) { + r--; + }else if (r == 0 && g ==0 && b == 0){ + toWhite = true; + } + } + return new Color(r, g, b); + + } +} diff --git a/src/com/sagi/dayan/Games/Stage/Scene.java b/src/com/sagi/dayan/Games/Stage/Scene.java new file mode 100644 index 0000000..ae08d57 --- /dev/null +++ b/src/com/sagi/dayan/Games/Stage/Scene.java @@ -0,0 +1,36 @@ +package com.sagi.dayan.Games.Stage; + +/** + * Created by sagi on 2/8/16. + */ + +import com.sagi.dayan.Games.Elements.*; +import com.sagi.dayan.Games.Engine.GameEngine; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.KeyListener; +import java.awt.event.MouseAdapter; +import java.awt.image.BufferedImage; + +public abstract class Scene extends MouseAdapter implements KeyListener{ + + protected int stageWidth, stageHeight; + protected BufferedImage sceneImage; + protected GameEngine engine; + + public Scene (int stageWidth, int stageHeight, GameEngine engine) { + this.stageWidth = stageWidth; + this.stageHeight = stageHeight; + this.engine = engine; + } + + public abstract void update (); + + public abstract void render(JPanel p); + + public BufferedImage getSceneImage () { + return sceneImage; + } + +} diff --git a/src/com/sagi/dayan/Games/Stage/SettingsMenuScene.java b/src/com/sagi/dayan/Games/Stage/SettingsMenuScene.java new file mode 100644 index 0000000..2f5036b --- /dev/null +++ b/src/com/sagi/dayan/Games/Stage/SettingsMenuScene.java @@ -0,0 +1,63 @@ +package com.sagi.dayan.Games.Stage; + +import com.sagi.dayan.Games.Engine.GameEngine; +import com.sagi.dayan.Games.Utils.Utils; +import sun.audio.AudioPlayer; +import sun.audio.AudioStream; + +import javax.imageio.ImageIO; +import javax.swing.*; +import java.awt.*; +import java.awt.event.KeyEvent; +import java.awt.image.BufferedImage; +import java.io.IOException; + +/** + * Created by sagi on 2/27/16. + */ +public class SettingsMenuScene extends Scene { + private BufferedImage background; + + + public SettingsMenuScene(int stageWidth, int stageHeight, GameEngine engine) { + super(stageWidth, stageHeight, engine); + try { + background = ImageIO.read(Utils.getImageResourceAsURL("Settigns_menu.jpg")); + } catch (IOException e) { + e.printStackTrace(); + } + } + + @Override + public void update() { + + } + + @Override + public void render(JPanel p) { + sceneImage = new BufferedImage(this.stageWidth, this.stageHeight, Image.SCALE_FAST); + Graphics g = sceneImage.getGraphics(); + g.drawImage(background, 0,0,p); + + } + + @Override + public void keyTyped(KeyEvent keyEvent) { + + } + + @Override + public void keyPressed(KeyEvent keyEvent) { + switch (keyEvent.getKeyCode()){ + case KeyEvent.VK_ESCAPE: + Utils.playSound("menuItem.wav"); + engine.goToMainMenu(); + break; + } + } + + @Override + public void keyReleased(KeyEvent keyEvent) { + + } +} diff --git a/src/com/sagi/dayan/Games/Stage/Stage.java b/src/com/sagi/dayan/Games/Stage/Stage.java new file mode 100644 index 0000000..48bbc87 --- /dev/null +++ b/src/com/sagi/dayan/Games/Stage/Stage.java @@ -0,0 +1,109 @@ +package com.sagi.dayan.Games.Stage; + +import com.sagi.dayan.Games.Engine.GameEngine; +import com.sagi.dayan.Games.Utils.Utils; + +import javax.swing.*; +import java.awt.*; +import java.awt.image.BufferStrategy; +import java.util.Vector; + +/** + * Created by sagi on 2/8/16. + */ +public class Stage extends JPanel implements Runnable{ + + private Vector scenes; + private int currentScene; + private int fWidth, fHeight; + private long startTime; + private GameEngine engine; + + + + public Stage(int width, int height) { + this.setDoubleBuffered(true); + this.fHeight = height; + this.setSize(width, height); + this.setVisible(true); + this.scenes = new Vector<>(); + this.engine = new GameEngine(width, height, this); + startTime = System.currentTimeMillis(); + currentScene = 0; + + + + this.setFocusable(true); + this.requestFocus(); + } + + public synchronized void update() { + engine.update(); + } + + public synchronized void render() { + engine.render(this); + } + + @Override + public void paintComponent(Graphics g) { +// System.out.println("Paint Component"); + super.paintComponent(g); + g.drawImage(engine.getScene(),0,0,this); + g.dispose(); + } + + @Override + public void run() { + double nsPerTick = 1000000000D / 60D; // ( 1 Billion / 60) + long lastTimer = System.currentTimeMillis(); + boolean toRender = false; + long lastTime = System.nanoTime(); + int ticks = 0; + int frames = 0; + double delta = 0; + + while(engine.gameOn){ + + long now = System.nanoTime(); + delta += (now - lastTime) / nsPerTick; + lastTime = now; + + if (delta >= 1) { + update(); + ticks++; + delta -= 1; + toRender = true; + } + + if (toRender) { // render + frames++; + render(); + toRender = false; + repaint(); + } + + try { + Thread.sleep(20); + } catch (Exception e) { + e.printStackTrace(); + } + + if (System.currentTimeMillis() - lastTimer > 1000) { + lastTimer += 1000; + System.out.println("Ticks: " + ticks + "\tFps: " + frames + "\tScenes Size: " + engine.getScenesSize()); + frames = 0; + ticks = 0; + } + + } + } + + + @Override + public void addNotify(){ + super.addNotify(); + (new Thread(this)).start(); + } + +} diff --git a/src/com/sagi/dayan/Games/Utils/Utils.java b/src/com/sagi/dayan/Games/Utils/Utils.java new file mode 100644 index 0000000..5d9d1a4 --- /dev/null +++ b/src/com/sagi/dayan/Games/Utils/Utils.java @@ -0,0 +1,46 @@ +package com.sagi.dayan.Games.Utils; + +import sun.audio.AudioPlayer; +import sun.audio.AudioStream; + +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; + +/** + * Created by sagi on 2/24/16. + */ +public class Utils { + + public static InputStream getSoundResourceAsStream(String soundFileName){ + return Utils.class.getResourceAsStream("/com/sagi/dayan/Games/Sounds/" + soundFileName); + } + + public static URL getSoundResourceAsURL(String soundFileName){ + return Utils.class.getResource("/com/sagi/dayan/Games/Sounds/" + soundFileName); + } + + public static InputStream getImageResourceAsStream(String soundFileName){ + return Utils.class.getResourceAsStream("/com/sagi/dayan/Games/Images/" + soundFileName); + } + + public static URL getImageResourceAsURL(String soundFileName){ + return Utils.class.getResource("/com/sagi/dayan/Games/Images/" + soundFileName); + } + + public static void playSound(String soundFileName){ + try { + AudioPlayer.player.start(new AudioStream(Utils.getSoundResourceAsStream(soundFileName))); + } catch (IOException e) { + e.printStackTrace(); + } + } + + public static String getFontPath(String fontFileName) { + return Utils.class.getResource("/com/sagi/dayan/Games/Fonts/" + fontFileName).toString(); + } + + public static InputStream getFontStream(String fontFileName) { + return Utils.class.getResourceAsStream("/com/sagi/dayan/Games/Fonts/" + fontFileName); + } +}