Stage.java
package juego;
import java.awt.image.ImageObserver;
public interface Stage extends ImageObserver {
public static final int WIDTH = 800;
public static final int HEIGHT = 544;
public static final int PLAY_HEIGHT = 544;
public SpriteCache getSpriteCache();
public SoundCache getSoundCache();
public void addBala(Actor a);
public void terminarTurno();
public void gameOver();
}
Main.javapackage juego;
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.TexturePaint;
import java.awt.Transparency;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.image.BufferStrategy;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Main extends Canvas implements Stage, KeyListener{
private BufferStrategy strategy;
private SpriteCache spriteCache;
private SoundCache soundCache;
private int segundos;
private int turno = 0;
private ArrayList jugadores;
private ArrayList bala;
private long usedTime; //Fps
private boolean gameEnded = false;
private BufferedImage background, backgroundTile;;
public Main(){
spriteCache = new SpriteCache();
soundCache = new SoundCache();
JFrame ventana = new JFrame("Guerra de tanques");
JPanel panel = (JPanel) ventana.getContentPane();
setBounds(0,0,Stage.WIDTH,Stage.HEIGHT);
panel.setPreferredSize(new Dimension(Stage.WIDTH,Stage.HEIGHT));
//panel.setBackground(Color.black);
panel.setLayout(null);
panel.add(this);
ventana.setBounds(0, 0, Stage.WIDTH, Stage.HEIGHT);
ventana.setVisible(true);
ventana.addWindowListener(new WindowAdapter(){
public void windowClosing(WindowEvent e){
System.exit(0);
}
});
ventana.setResizable(false);
createBufferStrategy(2);
strategy = getBufferStrategy();
requestFocus();
addKeyListener(this);
setIgnoreRepaint(true);
}
public static void main(String[] args){
final Main main = new Main();
Thread thread1 = new Thread () {
public void run () {
main.PlayGame();
}
};
Thread thread2 = new Thread () {
public void run () {
main.empezarContador();
}
};
thread1.start();
thread2.start();
}
public class Tarea extends Thread{
public Tarea(String str){
super(str);
}
}
public void PlayGame(){
usedTime = 1000;
initWorld();
while(isVisible() && !gameEnded && !jugadores.isEmpty()){
long startTime = System.currentTimeMillis();
updateWorld();
checkCollisions();
paintWorld();
usedTime = System.currentTimeMillis() - startTime;
do{
Thread.yield();
}while(System.currentTimeMillis() - startTime < 17);
}
paintGameOver();
}
public void initWorld(){
jugadores = new ArrayList();
for(int i = 1; i <= 2; i++){
Jugador j = new Jugador(this);
j.setY(Stage.HEIGHT - 200);
j.setX((int)(Math.random() * Stage.WIDTH) );
jugadores.add(j);
}
bala = new ArrayList();
backgroundTile = spriteCache.getSprite("fondo.jpg");
background = spriteCache.createCompatible(Stage.WIDTH,Stage.HEIGHT+backgroundTile.getHeight(),Transparency.OPAQUE);
Graphics2D g = (Graphics2D)background.getGraphics();
g.setPaint( new TexturePaint( backgroundTile,new Rectangle(0,0,backgroundTile.getWidth(),backgroundTile.getHeight())));
g.fillRect(0,0,background.getWidth(),background.getHeight());
}
public void updateWorld(){
for(int i = 0; i< jugadores.size(); i++){
Jugador j = (Jugador)jugadores.get(i);
if(j.isMarkedForRemoval()){
jugadores.remove(i);
}else{
j.act();
}
}
if(!bala.isEmpty()){
Bala b = (Bala)bala.get(0);
b.act();
}
}
public void paintWorld(){
Graphics2D g = (Graphics2D) strategy.getDrawGraphics();
g.drawImage(background, 0, 0, Stage.WIDTH, Stage.HEIGHT, 0, 0, Stage.WIDTH, Stage.HEIGHT, this);
//g.setColor(Color.black);
//g.fillRect(0, 0, Stage.WIDTH, Stage.HEIGHT);
for(int i = 0; i< jugadores.size(); i++){
Jugador j = (Jugador)jugadores.get(i);
j.paint(g);
}
if(!bala.isEmpty()){
Bala b = (Bala)bala.get(0);
b.paint(g);
}
paintStatus(g);
strategy.show();
}
public void paintStatus(Graphics2D g){
paintOptions(g);
paintShields(g);
}
public void paintOptions(Graphics2D g){
Jugador j = (Jugador) jugadores.get(turno);
g.setFont(new Font("Arial",Font.BOLD,30));
g.setPaint(Color.white);
g.drawString("Angulo: " + j.getAngleBala() , 0 , 30);
g.setFont(new Font("Arial",Font.BOLD,30));
g.setPaint(Color.white);
g.drawString("Speed: " + j.getSpeedBala() , 0 , 60);
g.setFont(new Font("Arial",Font.BOLD,30));
g.setPaint(Color.white);
g.drawString("" + segundos , Stage.WIDTH / 2 , 30);
}
public void paintShields(Graphics2D g){
Jugador j1 = (Jugador) jugadores.get(0);
g.setPaint(Color.red);
g.fillRect(100, Stage.PLAY_HEIGHT, j1.MAX_SHIELDS, 100);
g.setPaint(Color.blue);
g.fillRect(10 + j1.MAX_SHIELDS-j1.getShields(), Stage.PLAY_HEIGHT-60, j1.getShields(), 20);
Jugador j2 = (Jugador) jugadores.get(1);
g.setPaint(Color.red);
g.fillRect(100, Stage.PLAY_HEIGHT, j2.MAX_SHIELDS, 100);
g.setPaint(Color.blue);
g.fillRect(Stage.WIDTH - 20 - j2.MAX_SHIELDS , Stage.PLAY_HEIGHT-60, j2.getShields(), 20);
}
public void paintGameOver(){
Graphics2D g = (Graphics2D) strategy.getDrawGraphics();
g.setColor(Color.black);
g.fillRect(0,0,Stage.WIDTH,Stage.HEIGHT);
g.setFont( new Font("Arial",Font.BOLD,36));
g.setColor(Color.white);
g.drawString("Perdiste",10 ,Stage.HEIGHT -40);
strategy.show();
}
public void addBala(Actor a) {
bala.add(a);
}
public void checkCollisions(){
if(!bala.isEmpty()){
Bala b = (Bala)bala.get(0);
Rectangle balaBounds = b.getBounds();
for(int i = 0; i < jugadores.size(); i++){
Actor a1 = (Actor)jugadores.get(i);
Rectangle r1 = a1.getBounds();
if(r1.intersects(balaBounds)){
b.collision(a1);
a1.collision(b);
}
}
}
}
public void keyPressed(KeyEvent e) {
Jugador j = (Jugador) jugadores.get(turno);
j.keyPressed(e);
}
public void keyReleased(KeyEvent e) {
Jugador j = (Jugador) jugadores.get(turno);
j.keyReleased(e);
}
public void keyTyped(KeyEvent arg0) {}
public SpriteCache getSpriteCache() {
return spriteCache;
}
public SoundCache getSoundCache() {
return soundCache;
}
public void empezarContador(){
for(segundos = 30; segundos > 0; segundos--){
System.out.println(segundos);
delaySegundo();
}
changeTurno();
empezarContador();
}
private static void delaySegundo(){
try{
Thread.sleep(1000);
}catch(InterruptedException e){}
}
public void terminarTurno(){
bala.clear();
changeTurno();
}
public void changeTurno(){
if(!jugadores.isEmpty()){
Jugador j = (Jugador) jugadores.get(turno);
j.setVx(0);
if(turno < jugadores.size())
turno++;
if(turno == jugadores.size())
turno = 0;
segundos = 30;
}
}
public void gameOver() {
gameEnded = true;
}
}
Actor.javapackage juego;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;
public class Actor {
protected int x , y;
protected int width, height;
protected String [] spriteNames;
protected int currentFrame;
protected int frameSpeed;
protected int t;
protected Stage stage;
protected SpriteCache spriteCache;
protected boolean markedForRemoval;
public Actor(Stage stage){
this.stage = stage;
spriteCache = stage.getSpriteCache();
currentFrame = 0;
frameSpeed = 1;
t = 0;
}
public void paint(Graphics2D g){
g.drawImage(spriteCache.getSprite(spriteNames[currentFrame]),x,y,stage);
}
public void remove(){
markedForRemoval = true;
}
public boolean isMarkedForRemoval(){
return markedForRemoval;
}
public int getX() { return x; }
public void setX(int x) { this.x = x;}
public int getY() { return y; }
public void setY(int y) { this.y = y; }
public int getWidth() { return width; }
public void setWidth(int width) { this.width = width;}
public int getHeight() { return height; }
public void setHeight(int height) { this.height = height; }
public int getFrameSpeed() {return frameSpeed; }
public void setFrameSpeed(int i) { frameSpeed = i; }
public void setSpriteNames(String[] names){
spriteNames = names;
height = 0;
width = 0;
for(int i = 0; i < names.length; i++){
BufferedImage image = spriteCache.getSprite(spriteNames[i]);
height = Math.max(height,image.getHeight());
width = Math.max(width,image.getWidth());
}
}
public Rectangle getBounds(){
return new Rectangle(x,y,width,height);
}
public void collision(Actor a){
}
public void act(){
t++;
if(t % frameSpeed == 0){
t = 0;
currentFrame = (currentFrame + 1) % spriteNames.length;
}
}
}
Jugador.javapackage juego;
import java.awt.event.KeyEvent;
public class Jugador extends Actor{
public static final int MAX_SHIELDS = 200;
protected int vx;
private boolean left = false;
private boolean right = false;
private boolean izq = false;
private boolean der = false;
private int speed = 3;
private int shields;
private double angleBala = 5;
private int speedBala = 10;
public Jugador(Stage stage){
super(stage);
setSpriteNames(new String[]{ "tanque.gif" });
shields = MAX_SHIELDS;
}
public void act(){
super.act();
x += vx;
if(x < 0)
x = 0;
if(x > Stage.WIDTH - getWidth())
x = Stage.WIDTH - getWidth();
}
public void updateSpeed(){
vx = 0;
if(left) vx = -speed;
if(right) vx = speed;
}
public void keyPressed(KeyEvent e){
switch(e.getKeyCode()){
case KeyEvent.VK_LEFT:
left = true;
izq = true;
der = false;
break;
case KeyEvent.VK_RIGHT:
right = true;
izq = false;
der = true;
break;
case KeyEvent.VK_SPACE:
fire();
break;
case KeyEvent.VK_UP:
if(angleBala < 90)
angleBala +=5;
break;
case KeyEvent.VK_DOWN:
if(angleBala > 0)
angleBala-=5;
break;
case KeyEvent.VK_X:
if(speedBala < 20)
speedBala ++;
break;
case KeyEvent.VK_Z:
if(speedBala > 6)
speedBala --;
break;
}
updateSpeed();
}
public void keyReleased(KeyEvent e){
switch(e.getKeyCode()){
case KeyEvent.VK_LEFT:
left = false;
break;
case KeyEvent.VK_RIGHT:
right = false;
break;
}
updateSpeed();
}
public void fire(){
Bala b = new Bala(stage);
b.setX(b.getWidth() + x);
b.setY(y - b.getHeight());
b.setSpeed(speedBala);
b.setAngle(angleBala);
b.applyFriction();
b.setRight(der);
b.setLeft(izq);
stage.addBala(b);
}
public void collision(Actor a){
if(a instanceof Bala){
addShields(-40);
stage.terminarTurno();
}
if(getShields() <= 0)
stage.gameOver();
}
public int getVx() {
return vx;
}
public void setVx(int vx) {
this.vx = vx;
}
public int getSpeed() {
return speed;
}
public void setSpeed(int speed) {
this.speed = speed;
}
public double getAngleBala() {
return angleBala;
}
public void setAngleBala(float angleBala) {
this.angleBala = angleBala;
}
public int getSpeedBala() {
return speedBala;
}
public void setSpeedBala(int speedBala) {
this.speedBala = speedBala;
}
public int getShields() {
return shields;
}
public void setShields(int shields) {
this.shields = shields;
}
public void addShields(int i){
shields += i;
if(shields > MAX_SHIELDS) shields = MAX_SHIELDS;
}
}
Bala.javapackage juego;
public class Bala extends Actor{
private double angle;
private int speed;
private float vx;
private float vy;
private float gravity = 0.5f;
private boolean left;
private boolean right;
public void applyFriction(){
float radians = (float)((angle / 180) * Math.PI )*-1;
vx = (float) (speed * Math.cos(radians));
vy = (float) (speed * Math.sin(radians));
}
public Bala(Stage stage) {
super(stage);
setSpriteNames(new String[] {"bala.gif"});
}
public void act(){
super.act();
if(left)
x -= vx;
if(right)
x += vx;
vy += gravity;
y += vy;
System.out.println("X: " + x + " Y: " + y);
if(x < 0 || x > Stage.WIDTH || y > Stage.HEIGHT - 100){
stage.terminarTurno();
}
}
public double getAngle() {
return angle;
}
public void setAngle(double angle) {
this.angle = angle;
}
public int getSpeed() {
return speed;
}
public void setSpeed(int speed) {
this.speed = speed;
}
public boolean isLeft() {
return left;
}
public void setLeft(boolean left) {
this.left = left;
}
public boolean isRight() {
return right;
}
public void setRight(boolean right) {
this.right = right;
}
}
ResourceCache.javapackage juego;
import java.net.URL;
import java.util.HashMap;
public abstract class ResourceCache {
@SuppressWarnings("rawtypes")
protected HashMap resources;
@SuppressWarnings("rawtypes")
public ResourceCache(){
resources = new HashMap();
}
protected Object loadResource(String name){
URL url = null;
url = getClass().getClassLoader().getResource(name);
return loadResource(url);
}
@SuppressWarnings("unchecked")
protected Object getResource(String name){
Object res = resources.get(name);
if(res == null){
res = loadResource("res/" + name);
resources.put(name, res);
}
return res;
}
protected abstract Object loadResource(URL url);
}
SoundCache.javapackage juego;
import java.applet.Applet;
import java.applet.AudioClip;
import java.net.URL;
public class SoundCache extends ResourceCache{
protected Object loadResource(URL url) {
return Applet.newAudioClip(url);
}
public AudioClip getAudioClip(String name){
return (AudioClip) getResource(name);
}
public void playSound(final String name){
new Thread(
new Runnable() {
public void run() {
getAudioClip(name).play();
}
}
).start();
}
public void loopSound(final String name){
new Thread(
new Runnable() {
public void run() {
getAudioClip(name).loop();
}
}
).start();
}
public void stopSound(final String name){
getAudioClip(name).stop();
}
}
SpriteCache.javapackage juego;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsEnvironment;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.awt.image.ImageObserver;
import java.net.URL;
import javax.imageio.ImageIO;
public class SpriteCache extends ResourceCache implements ImageObserver{
protected Object loadResource(URL url){
try{
return ImageIO.read(url);
}catch(Exception e){
System.out.println("No se pudo cargar la imagen de " + url);
System.out.println("El error fue: " + e.getClass().getName() + " " + e.getMessage());
System.out.println(0);
return null;
}
}
public BufferedImage getSprite(String name){
return (BufferedImage) getResource(name);
}
public BufferedImage createCompatible(int width, int height, int transparency){
GraphicsConfiguration gc =
GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration();
BufferedImage compatible = gc.createCompatibleImage(width, height, transparency);
return compatible;
}
public boolean imageUpdate(Image img, int infoflags, int x, int y,int width, int height) {
return (infoflags & (ALLBITS|ABORT)) == 0;
}
}