package com.touchspin.td;
import java.util.ArrayList;
import java.util.HashSet;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.math.Vector2;
/* ======================================================================================
* File: MoverBall.java
* Authors: Brian Adams - b.adams5736@edmail.edcc.edu
* Russell Brendel - russell.brendel.2925@edmail.edcc.edu
* Damian Forrester - dforrester777@gmail.com
* Wendi Tang - w.tang2404@myedmail.edcc.edu
*
* Organization: Edmonds Community College
* Term: Spring 2014
* Class: CS 185 - Game Project Developement
* Instructor: Tim Hunt - thunt@edcc.edu
*
* Project: Ollie
* --------------------------------------------------------------------------------------
*
* This class handles ball movement which includes elastic collision
*
* ======================================================================================
*/
public class MoverBall extends MoverPhysics {
private HashSet<NP> prev = new HashSet<NP>();
public ArrayList<Balls> acted = new ArrayList<Balls>();
private Balls ball;
private Vector2 speed = new Vector2();
/**
* Defualt constructor
* @param ball assign the ball to this mover
*/
public MoverBall(Balls ball) {
super();
this.ball = ball;
}
/**
* Move balls and handle the elastic collision
*/
@Override
public void move(GameThing gameThing) {
this.gameThing = gameThing;
previousX = gameThing.getX();
previousY = gameThing.getY();
physicsMove();
gameThing.setX(gameThing.getX() + Gdx.graphics.getDeltaTime()
* speedXPerSecond);
if (!isXFree()) {
gameThing.setX(previousX);
speedXPerSecond = -0.5f * speedXPerSecond;
}
gameThing.setY(gameThing.getY() + Gdx.graphics.getDeltaTime()
* speedYPerSecond);
if (!isYFree()) {
gameThing.setY(previousY);
speedYPerSecond = -0.5f * speedYPerSecond;
}
ballCollisionDetection();
if (triggeredNP.size() != 0) {
for (NP object : triggeredNP) {
if (!prev.contains(object) && object.active) {
g.i().t.action(object.conditions, object.action);
}
}
prev.clear();
for (NP object : triggeredNP) {
prev.add(object);
}
triggeredNP.clear();
} else {
prev.clear();
}
}
/**
* Detect ball collision
*/
private void ballCollisionDetection()
{
if( g.i().hero.getCenter().dst(ball.getCenter()) < (g.i().hero.radius+ball.radius))
{
float collisionDepth = 1 + Math.abs(g.i().hero.radius+ball.radius - g.i().hero.getCenter().dst(ball.getCenter()));
speed.set(g.i().hero.getXSpeed(),g.i().hero.getYSpeed()).nor();
g.i().hero.setX(g.i().hero.getX()-speed.x*collisionDepth);
g.i().hero.setY(g.i().hero.getY()-speed.y*collisionDepth);
ballElsaticCollision(ball,g.i().hero);
}
for (Balls theOtherBall : g.i().balls)
{
if(!(acted.contains(theOtherBall)||theOtherBall.equals(ball)))
{
if(theOtherBall.getCenter().dst(ball.getCenter()) < (theOtherBall.radius+ball.radius))
{
theOtherBall.ballMover.acted.add(theOtherBall);
ballElsaticCollision(ball,theOtherBall);
}
}
}
}
/**
* Handle ball to ball elastic collision reaction
* @param ball1 - the first ball
* @param ball2 - the second ball
*/
private void ballElsaticCollision(Balls ball1, Balls ball2)
{
Vector2 v = new Vector2(ball1.getXSpeed()-ball2.getXSpeed(),ball1.getYSpeed()-ball2.getYSpeed());
Vector2 n = new Vector2(ball2.getCenter().x-ball1.getCenter().x,ball2.getCenter().y-ball1.getCenter().y);
float mr = ball1.mass/ball2.mass;
Vector2 dV2 = new Vector2(ball2.getXSpeed(),ball2.getYSpeed());
Vector2 u = new Vector2(ball1.getXSpeed()-dV2.x,ball1.getYSpeed()-dV2.y);
float imn = (float) (1/Math.pow((n.x*n.x+n.y*n.y),0.5));
float mv = (float) Math.pow((v.x*v.x+v.y*v.y),0.5); // magnitude of v
float cun = (float) (mv*Math.cos(Math.atan2(n.y,n.x)-Math.atan2(u.y, u.x)));
float sf = cun*imn;
Vector2 un = new Vector2(n.x*sf,n.y*sf);
Vector2 ut = new Vector2(u.x - un.x,u.y - un.y);
float num = mr - 1;
float invDen = 1/(mr + 1);
Vector2 vn= new Vector2(un.x*num*invDen,un.y*num*invDen);
Vector2 wn = new Vector2(un.x*2*mr*invDen,un.y*2*mr*invDen);
Vector2 nuDV1 = new Vector2(ut.x+vn.x+dV2.x,ut.y+vn.y+dV2.y);
Vector2 nuDV2 = new Vector2(wn.x+dV2.x,wn.y+dV2.y);
ball1.ballMover.speedXPerSecond=nuDV1.x;
ball1.ballMover.speedYPerSecond=nuDV1.y;
ball2.ballMover.speedXPerSecond=nuDV2.x;
ball2.ballMover.speedYPerSecond=nuDV2.y;
}
/**
* Handle ball to player elastic collision reaction
* @param ball1 - the first ball
* @param ball2 - the player
*/
private void ballElsaticCollision(Balls ball1, Hero ball2)
{
Vector2 v = new Vector2(ball1.getXSpeed()-ball2.getXSpeed(),ball1.getYSpeed()-ball2.getYSpeed());
Vector2 n = new Vector2(ball2.getCenter().x-ball1.getCenter().x,ball2.getCenter().y-ball1.getCenter().y);
float mr = ball1.mass/ball2.mass;
Vector2 dV2 = new Vector2(ball2.getXSpeed(),ball2.getYSpeed());
Vector2 u = new Vector2(ball1.getXSpeed()-dV2.x,ball1.getYSpeed()-dV2.y);
float imn = (float) (1/Math.pow((n.x*n.x+n.y*n.y),0.5));
float mv = (float) Math.pow((v.x*v.x+v.y*v.y),0.5); // magnitude of v
float cun = (float) (mv*Math.cos(Math.atan2(n.y,n.x)-Math.atan2(u.y, u.x)));
float sf = cun*imn;
Vector2 un = new Vector2(n.x*sf,n.y*sf);
Vector2 ut = new Vector2(u.x - un.x,u.y - un.y);
float num = mr - 1;
float invDen = 1/(mr + 1);
Vector2 vn= new Vector2(un.x*num*invDen,un.y*num*invDen);
Vector2 wn = new Vector2(un.x*2*mr*invDen,un.y*2*mr*invDen);
Vector2 nuDV1 = new Vector2(ut.x+vn.x+dV2.x,ut.y+vn.y+dV2.y);
Vector2 nuDV2 = new Vector2(wn.x+dV2.x,wn.y+dV2.y);
ball1.ballMover.speedXPerSecond=nuDV1.x;
ball1.ballMover.speedYPerSecond=nuDV1.y;
ball2.heroMover.speedXPerSecond=nuDV2.x;
ball2.heroMover.speedYPerSecond=nuDV2.y;
}
/**
* Handle physics movement for balls
*/
@Override
protected void physicsMove() {
isInWater();
fractionFactor = ball.friction;
if (isInWater) {
speedXPerSecond *= (1 - fractionFactor * 2);
speedYPerSecond *= (1 - fractionFactor * 2);
} else {
speedXPerSecond *= (1 - fractionFactor);
speedYPerSecond *= (1 - fractionFactor);
}
speedXPerSecond += accelerationX;
speedYPerSecond += accelerationY;
if (g.i().gameMode == 'R') {
if (isInWater) {
speedYPerSecond += (maxDyInwater < ball.dyInWater)?maxDyInwater:ball.dyInWater;
} else
speedYPerSecond += gravityPerSecond;
}
radius = gameThing.getWidth() / 2;
tileWidth = tileHeight = 32;
}
}