Juego de pelotas con efecto de rebote con canvas y vectores 2d

Technology

header ads

Juego de pelotas con efecto de rebote con canvas y vectores 2d

bueno hace tiempo habia publicado un video youtube sobre el efecto de rebote de unas pelotas que salian de la parte inferior de una jframe en java y saltaban como si tuvieran gravedad el video lo pueden ver aqui  VER VIDEO  la imagen de la interfaz del programa:

Juego de pelotas con efecto de rebote con canvas y vectores  2d


bueno  al grano tenemos  6 clases dentro del pakete animaciones como lo muestra la siguiente imagen:


espesemos con la clase Accel en esa clase ponemos el siguiente codigo:
















package animaciones;


/*
 
 http://javayotros.blogspot.com/*/
public class Accel
{
	private double ax, ay;

	public Accel(double ax, double ay)
	{
		this.ax = ax;
		this.ay = ay;
	}

	public double ax()
	{
		return this.ax;
	}

	public double ay()
	{
		return this.ay;
	}
}
luego tenemos otra clase MakeBall donde pondremos el siguiente codigo:



package animaciones;
/*
 
 http://javayotros.blogspot.com/
 */
public class MakeBall extends Thread
{
  public void run()
  {
    while (Main.isRunning) {
      Main.giveBirth(1, 1, Math.random() * 1000.0,
                     Math.random() * 1000.0, 100);
      try 
      {
        sleep(500);
      } 
      catch (InterruptedException e) 
      {
      }
    }
  }
}

luego creamos otra clase llamada MoveEngine donde pondremos el siguiente codigo:



package animaciones;

import java.awt.geom.Point2D;
import java.util.ArrayList;
/*
 http://javayotros.blogspot.com/
 */
public class MoveEngine extends Thread
{
	private long timePassed = 0;
	private long curTime = 0;
	private long lastTime = 0;
	private double timeFraction = 0.0;
	private ArrayList constForces = new ArrayList();

	public void run()
	{
		curTime = System.currentTimeMillis();
		initializeConstForces();
		while (Main.isRunning) {
			updateTime();
			applyConstForces();
			sumForces();
			moveEnts();
			try {
				sleep(1);
			} catch (InterruptedException e) {
			}
		}
	}

	private void updateTime()
	{
		lastTime = curTime;
		curTime = System.currentTimeMillis();
		timePassed = (curTime - lastTime);
		timeFraction = (timePassed / 1000.0);
	}

	private void initializeConstForces()
	{
		constForces.add(new Accel(0.0, Main.GRAVITY));
	}

	private synchronized void applyConstForces()
	{
		double xAccel = 0, yAccel = 0;
		// Find the total acceleration of all const forces.
		for (int i = 0; i < constForces.size(); i++) {
			xAccel += constForces.get(i).ax();
			yAccel += constForces.get(i).ay();
		}
		// Apply the sum acceleration to each entity.
		for (int i = 0; i < Main.living.size(); i++) {
			Spawn s = Main.living.get(i);
			s.addAccel(new Accel(xAccel, yAccel));
		}
	}

	private synchronized void sumForces()
	{
		for (int i = 0; i < Main.living.size(); i++) {
			Spawn s = Main.living.get(i);
			// Get the sum of all accelerations acting on object.
			Accel theAccel = s.sumAccel();//aqui hace algo
			// Apply the resulting change in velocity.
			double vx = s.vx() + (theAccel.ax() * timeFraction);
			double vy = s.vy() + (theAccel.ay() * timeFraction);
			s.updateVelocity(vx, vy);
			// Apply drag coefficient
			s.applyDrag(1.0 - (timeFraction * Main.DRAG));
		}
	}

	private synchronized void moveEnts()
	{
		for (int i = 0; i < Main.living.size(); i++) {
			Spawn s = Main.living.get(i);
			// Get the initial x and y coords.
			double oldX = s.getX(), oldY = s.getY();
			// Calculate the new x and y coords.
			double newX = oldX + (s.vx() * timeFraction);
			double newY = oldY + (s.vy() * timeFraction);
			s.updatePos(newX, newY);
			checkWallCollisions(s);
		}
		checkCollisions();
	}

	private synchronized void checkCollisions()
	{
		for (int i = 0; i < Main.living.size() - 1; i++) {
			Spawn s = Main.living.get(i);
			Point2D sCenter = s.getCenter();
			for (int j = i + 1; j < Main.living.size(); j++) {
				Spawn t = Main.living.get(j);
				if (t == null) break;
				Point2D tCenter = t.getCenter();
				double distBetween = sCenter.distance(tCenter);
				double bigR = s.getRadius() > t.getRadius() ? s.getRadius() : t
						.getRadius();
				if (distBetween < (bigR * 2)) collide(s, t, distBetween);
			}
		}
	}

	private synchronized void collide(Spawn s, Spawn t, double distBetween)
	{
		// Get the relative x and y dist between them.
		double relX = s.getX() - t.getX();
		double relY = s.getY() - t.getY();
		// Take the arctan to find the collision angle.
		double collisionAngle = Math.atan2(relY, relX);
		// if (collisionAngle < 0) collisionAngle += 2 * Math.PI;
		// Rotate the coordinate systems for each object's velocity to align
		// with the collision angle. We do this by supplying the collision angle
		// to the vector's rotateCoordinates method.
		Vector2D sVel = s.velVector(), tVel = t.velVector();
		sVel.rotateCoordinates(collisionAngle);
		tVel.rotateCoordinates(collisionAngle);
		// In the collision coordinate system, the contact normals lie on the
		// x-axis. Only the velocity values along this axis are affected. We can
		// now apply a simple 1D momentum equation where the new x-velocity of
		// the first object equals a negative times the x-velocity of the
		// second.
		double swap = sVel.x;
		sVel.x = tVel.x;
		tVel.x = swap;
		// Now we need to get the vectors back into normal coordinate space.
		sVel.restoreCoordinates();
		tVel.restoreCoordinates();
		// Give each object its new velocity.
		s.updateVelocity(sVel.x * Main.BOUNCE, sVel.y * Main.BOUNCE);
		t.updateVelocity(tVel.x * Main.BOUNCE, tVel.y * Main.BOUNCE);
		// Back them up in the opposite angle so they are not overlapping.
		double minDist = s.getRadius() + t.getRadius();
		double overlap = minDist - distBetween;
		double toMove = overlap / 2;
		double newX = s.getX() + (toMove * Math.cos(collisionAngle));
		double newY = s.getY() + (toMove * Math.sin(collisionAngle));
		s.updatePos(newX, newY);
		newX = t.getX() - (toMove * Math.cos(collisionAngle));
		newY = t.getY() - (toMove * Math.sin(collisionAngle));
		t.updatePos(newX, newY);
	}

	private synchronized void checkWallCollisions(Spawn s)
	{
		int maxY = 480 - s.dimY();
		int maxX = 640 - s.dimX();
		if (s.getY() > maxY) {
			s.updatePos(s.getX(), maxY);
			s.updateVelocity(s.vx(), (s.vy() * -Main.BOUNCE));
		}
		if (s.getX() > maxX) {
			s.updatePos(maxX, s.getY());
			s.updateVelocity((s.vx() * -Main.BOUNCE), s.vy());
		}
		if (s.getX() < 1) {
			s.updatePos(1, s.getY());
			s.updateVelocity((s.vx() * -Main.BOUNCE), s.vy());
		}
	}
}

luego creamos una clase llamada Spawn pondremos el siguiente codigo:



package animaciones;

import java.awt.geom.Point2D;
import java.util.ArrayList;
/*
 http://javayotros.blogspot.com/
 */
public class Spawn
{
  private double x, y, vx, vy, radius;
  private ArrayList accelerations = new ArrayList();

  public Spawn(int x, int y, double vx, double vy, int m)
  {
    this.x = x;
    this.y = y;
    this.vx = vx;
    this.vy = vy;
    this.radius = 15.0;
  }

  public Spawn(int x, int y)
  {
    this(x, y, 0.0, 0.0, 100);
  }

  public Vector2D velVector()
  {
    return new Vector2D(this.vx(), this.vy());
  }

  public void applyDrag(double drag)
  {
    this.vx = (drag * this.vx);
    this.vy = (drag * this.vy);
  }

  public Accel sumAccel()
  {
    double xAccel = 0, yAccel = 0;
    for (int i = 0; i < this.accelerations.size(); i++) {
      xAccel += this.accelerations.get(i).ax();
      yAccel += this.accelerations.get(i).ay();
    }
    this.accelerations.clear();
    return new Accel(xAccel, yAccel);
  }

  public void addAccel(Accel a)
  {
    this.accelerations.add(a);
  }

  public void updateVelocity(double vx, double vy)
  {
    this.vx = vx;
    this.vy = vy;
  }

  public void updatePos(double newX, double newY)
  {
    this.x = newX;
    this.y = newY;
  }

  public double vx()
  {
    return this.vx;
  }

  public double vy()
  {
    return this.vy;
  }

  public int dimX()
  {
    return (int) (this.radius * 2);
  }

  public int dimY()
  {
    return (int) (this.radius * 2);
  }

  public Point2D getCenter()
  {
    return new Point2D.Double(this.x + (this.dimX() / 2), this.y
                              + (this.dimY() / 2));
  }

  public double getRadius()
  {
    return this.radius;
  }

  public double getX()
  {
    return this.x;
  }

  public double getY()
  {
    return this.y;
  }

  public double getX2()
  {
    return (this.x + this.dimX());
  }

  public double getY2()
  {
    return (this.y + this.dimY());
  }

  public void setX(int newX)
  {
    this.x = newX;
  }

  public void setY(int newY)
  {
    this.y = newY;
  }
}


luego creamos una clase llamada Vector2D donde pondremos el siguiente codigo:


package animaciones;

public class Vector2D
{
	public double x;
	public double y;
	public double restoreAngle;

	public Vector2D(double x, double y)
	{
		this.x = x;
		this.y = y;
		this.restoreAngle = 0.0;
	}

	public double angle()
	{
		return Math.atan2(y, x);
	}

	public double mag()
	{
		return Math.sqrt((x * x) + (y * y));
	}

	public void rotateCoordinates(double tiltAngle)
	{
		this.restoreAngle += tiltAngle;
		double angle = angle();
		double mag = mag();
		angle -= tiltAngle;
		x = mag * Math.cos(angle);
		y = mag * Math.sin(angle);
	}

	public void restoreCoordinates()
	{
		double angle = angle();
		double mag = mag();
		angle += restoreAngle;
		x = mag * Math.cos(angle);
		y = mag * Math.sin(angle);
		restoreAngle = 0.0;
	}
}



por ultimo la clase Main donde pondremos el siguiente codigo:


package animaciones;

import java.awt.Canvas;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.geom.AffineTransform;
import java.awt.geom.Ellipse2D;
import java.awt.image.BufferStrategy;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import javax.swing.JFrame;
/*
 
 http://javayotros.blogspot.com/
 */
public class Main
{
  public static final int MAX_SPAWN = 50;
  public static final int X = 640;
  public static final int Y = 480;
  public static final double GRAVITY = 1500;
  public static final double DRAG = 0.2;
  public static final double BOUNCE = 0.9;
  public static final String TITLE = "Mike's 2D Physics Engine";
  private static JFrame f;
  private static Canvas c;
  public static BufferStrategy b;
  private static GraphicsEnvironment ge;
  private static GraphicsDevice gd;
  private static GraphicsConfiguration gc;
  private static BufferedImage buffer;
  private static Graphics graphics;
  private static Graphics2D g2d;
  private static AffineTransform at;
  public static ArrayList living = new ArrayList();
  public static boolean isRunning = true;

  public static void main(String[] args)
  {
    // Initialize some things.
    initializeJFrame();
    // Create and start threads.
    Thread moveEngine = new MoveEngine();
    moveEngine.start();
    Thread makeBall = new MakeBall();
    makeBall.start();
    // Run the animation loop.
    runAnimation();
  }

  public static void runAnimation()
  {
    // Set up some variables.
    int fps = 0;
    int frames = 0;
    long totalTime = 0;
    long curTime = System.currentTimeMillis();
    long lastTime = curTime;
    // Start the loop.
    while (isRunning) {
      try {
        // Calculations for FPS.
        lastTime = curTime;
        curTime = System.currentTimeMillis();
        totalTime += curTime - lastTime;
        if (totalTime > 1000) {
          totalTime -= 1000;
          fps = frames;
          frames = 0;
        }
        ++frames;
        // clear back buffer...
        g2d = buffer.createGraphics();
        g2d.setColor(Color.white);
        g2d.fillRect(0, 0, X, Y);
        // Draw entities
        for (int i = 0; i = MAX_SPAWN) return 1;
    living.add(new Spawn(x, y, vx, vy, m));
    return 0;
  }

  private static void initializeJFrame()
  {
    // Create the frame...
    f = new JFrame(TITLE);
    f.setIgnoreRepaint(true);
    f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    // Create canvas for painting...
    c = new Canvas();
    c.setIgnoreRepaint(true);
    c.setSize(X, Y);
    // Add the canvas, and display.
    f.add(c);
    f.pack();
    // The following line centers the window on the screen.
    f.setLocationRelativeTo(null);
    f.setVisible(true);
    // Set up the BufferStrategy for double buffering.
    c.createBufferStrategy(2);
    b = c.getBufferStrategy();
    // Get graphics configuration...
    ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
    gd = ge.getDefaultScreenDevice();
    gc = gd.getDefaultConfiguration();
    // Create off-screen drawing surface
    buffer = gc.createCompatibleImage(X, Y);
    // Objects needed for rendering...
    graphics = null;
    g2d = null;
  }
}



a veces pasando de aca a la plataforma de programacion salen errores por lo que tocaria modificarlo manualmente por eso les dejo el link del codigo por mediafire Descargar Codigo

Post a Comment