My game has a player who is constantly moving up. I want it so when he hits the bottom of a block, you lose, and if he hits a block on the side, he just bounces back. There is no physics involved. For whatever reason, the collision detection just isn't working as it as supposed to. For example, in the code below I am resetting the position every time the player hits the bottom. However, it always resets before he even hits the bottom of the tile. Why is this happening and how can I fix it?
Below is my code for the player (GameIcon),:
package com.xx4everPixelatedxx.gaterunner.sprites;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.Sprite;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.maps.MapObject;
import com.badlogic.gdx.maps.objects.RectangleMapObject;
import com.badlogic.gdx.maps.tiled.TiledMap;
import com.badlogic.gdx.math.Intersector;
import com.badlogic.gdx.math.Rectangle;
import com.badlogic.gdx.math.Vector3;
import com.badlogic.gdx.physics.box2d.Body;
import com.badlogic.gdx.physics.box2d.BodyDef;
import com.badlogic.gdx.physics.box2d.FixtureDef;
import com.badlogic.gdx.physics.box2d.PolygonShape;
import com.xx4everPixelatedxx.gaterunner.GateRunner;
import com.xx4everPixelatedxx.gaterunner.gameObjects.Block;
import com.xx4everPixelatedxx.gaterunner.gameObjects.Spike;
import javax.xml.soap.Text;
/**
* Created by Michael Jan on 8/17/2015.
*/
public class GameIcon extends Sprite {
private float vX = 3;
private float vY = 3;
private float r = 9;
private Texture texture;
public GameIcon(int x, int y) {
super(new Texture(Gdx.files.internal("icon_players/icon1.png")));
setPosition(x, y);
// texture = new Texture(Gdx.files.internal("icon_players/icon1.png"));
// setTexture(texture);
}
public void update() {
addPosition(vX, vY);
setRotation( (getRotation() + r) % 360);
setOriginCenter();
}
public void update(TiledMap map) {
addPosition(vX, vY);
setRotation((getRotation() + r) % 360);
setOriginCenter();
//block
for(MapObject object : map.getLayers().get(2).getObjects().getByType(RectangleMapObject.class))
{
Rectangle rect = ((RectangleMapObject)object).getRectangle();
if(Intersector.overlaps(getBoundingRectangle(), rect))
{
setPosition(GateRunner.WIDTH/2 - GateRunner.WIDTH/20, GateRunner.HEIGHT/10);
if(getY() <= rect.getY() - getHeight() + vX)
{
System.out.println("bottom");
setPosition(GateRunner.WIDTH/2 - GateRunner.WIDTH/20, GateRunner.HEIGHT/10);
}
else
{
System.out.println("side");
negateVelocityX();
negateRotation();
}
}
}
//spike
for(MapObject object : map.getLayers().get(3).getObjects().getByType(RectangleMapObject.class))
{
Rectangle rect = ((RectangleMapObject)object).getRectangle();
if(rect.overlaps(getBoundingRectangle()))
{
}
}
}
public void addPosition(float x, float y) {
setPosition(getX() + x, getY() + y);
setOriginCenter();
}
public void negateVelocityX() {
if(vX < 0)
{
addPosition((int)(getWidth()*0.05), 0);
}
if(vX > 0)
{
addPosition(-(int)(getWidth()*0.05), 0);
}
vX = -vX;
}
public void negateRotation() {
r = -r;
}
public float getvX() {
return vX;
}
public void setvX(int vX) {
this.vX = vX;
}
public float getvY() {
return vY;
}
public void setvY(int vY) {
this.vY = vY;
}
public float getR() {
return r;
}
public void setR(int r) {
this.r = r;
}
}
Related
im triying to create a simple game, where my player, falls into different platforms. However, rigth now, im only able to detect the first collision.
I've tried making a loop, where i call HandleEvent(), but only works for the first platform.
How could i make it to detect every time the player collides with a platform? Thank you!
Player class:
package com.mygdx.juegoreto;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
import com.badlogic.gdx.math.Intersector;
import com.badlogic.gdx.math.Rectangle;
import java.util.ArrayList;
public class Personaje {
int x;
int y;
int width;
int height;
int xSpeed;
int ySpeed;
Color color;
public Personaje(int x, int y, int width, int height, int xSpeed, int ySpeed) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
this.xSpeed = xSpeed;
this.ySpeed = ySpeed;
this.color = Color.WHITE;
}
public void setxSpeed(int xSpeed) {
this.xSpeed = xSpeed;
}
public void setySpeed(int ySpeed) {
this.ySpeed = ySpeed;
}
public void update() {
x += xSpeed;
y += ySpeed;
if (x < 0 || x > Gdx.graphics.getWidth() - 70) {
xSpeed = -xSpeed;
}
if (y > Gdx.graphics.getHeight()) {
System.out.println("tas muerto");
}
}
public void draw(ShapeRenderer shape) {
shape.rect(x, y, width, height);
}
public void checkCollision(ArrayList<Plataforma> plats) {
if(collidesWith(plats)){
color = Color.GREEN;
}
else{
color = Color.WHITE;
}
}
private boolean collidesWith(ArrayList<Plataforma> plats) {
System.out.println("collides");
for (Plataforma plat : plats) {
if(x < plat.x + plat.width && y < plat.y + plat.height && x + width > plat.x && y + height > plat.y){
this.setySpeed(plat.ySpeed);
System.out.println("si");
return true;
}else{
this.setySpeed(-3);
System.out.println("no");
return false;
}
}
return true;
}
}
Main class:
package com.mygdx.juegoreto;
import com.badlogic.gdx.ApplicationAdapter;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
import com.badlogic.gdx.physics.box2d.Fixture;
import com.badlogic.gdx.utils.ScreenUtils;
import com.badlogic.gdx.graphics.GL20;
import java.util.ArrayList;
public class MyGame extends ApplicationAdapter {
ShapeRenderer shape;
Personaje player;
Plataforma plat;
ArrayList<Plataforma> plats;
private float timeSeconds = 0f;
private float period = 0f;
#Override
public void create () {
int x = Gdx.graphics.getWidth() / 2;
int y = Gdx.graphics.getHeight() ;
shape = new ShapeRenderer();
player = new Personaje(x, y - 200, 70, 70, 0, 0);
plat = new Plataforma(x - 70, y - 800, 200, 20,2);
plats = new ArrayList<>(1);
int altura = 0;
for(int i = 0; i <= 1 ; i++){
altura -= 160;
plats.add(new Plataforma((int)(Math.random() * Gdx.graphics.getWidth()), altura, 200, 20, 2));
}
}
#Override
public void render () {
ScreenUtils.clear(1, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
player.update();
//plat.update();
shape.begin(ShapeRenderer.ShapeType.Filled);
player.draw(shape);
//plat.draw(shape);
timeSeconds +=Gdx.graphics.getDeltaTime();
if(timeSeconds > period){
timeSeconds-=period;
handleEvent();
}
shape.end();
if (Gdx.input.isTouched()) {
if (Gdx.input.getX() < Gdx.graphics.getWidth() / 2){
player.setxSpeed(-2); //IZQUIERDA
} else {
player.setxSpeed(2); //DERECHA
}
}
if(player.y < -40){
System.out.println("tas muerto je");
}
/*for (Plataforma plat : plats ) {
int x = (int)(Math.random() * Gdx.graphics.getWidth());
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(x);
plat.draw(shape);
}*/
}
#Override
public void dispose () {
}
public void handleEvent() {
for (Plataforma plataforma : plats) {
plataforma.update();
plataforma.draw(shape);
}
player.checkCollision(plats);
}
}
I was not sure how to title this article. I am making a game that has sprite falling down. I already have triangles falling down in my game. I don't know how to change it where images that I import in the game that allows the image falling.
Icicle:
package com.udacity.gamedev.icicles;
import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
import com.badlogic.gdx.math.Vector2;
public class Icicle {
public static final String TAG = Icicle.class.getName();
Vector2 position;
Vector2 velocity;
public Icicle(Vector2 position) {
this.position = position;
this.velocity = new Vector2();
}
public void update(float delta) {
velocity.mulAdd(Constants.ICICLES_ACCELERATION, delta);
position.mulAdd(velocity, delta);
}
public void render(ShapeRenderer renderer) {
renderer.triangle(
position.x, position.y,
position.x - Constants.ICICLES_WIDTH / 2, position.y + Constants.ICICLES_HEIGHT,
position.x + Constants.ICICLES_WIDTH / 2, position.y + Constants.ICICLES_HEIGHT
);
}
}
Icicles:
package com.udacity.gamedev.icicles;
import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
import com.badlogic.gdx.math.MathUtils;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.utils.DelayedRemovalArray;
import com.badlogic.gdx.utils.viewport.Viewport;
import com.udacity.gamedev.icicles.Constants.Difficulty;
public class Icicles {
public static final String TAG = Icicles.class.getName();
Difficulty difficulty;
int iciclesDodged;
DelayedRemovalArray<Icicle> icicleList;
Viewport viewport;
public Icicles(Viewport viewport, Difficulty difficulty) {
this.difficulty = difficulty;
this.viewport = viewport;
init();
}
public void init() {
icicleList = new DelayedRemovalArray<Icicle>(false, 100);
iciclesDodged = 0;
}
public void update(float delta) {
if (MathUtils.random() < delta * difficulty.spawnRate) {
Vector2 newIciclePosition = new Vector2(
MathUtils.random() * viewport.getWorldWidth(),
viewport.getWorldHeight()
);
Icicle newIcicle = new Icicle(newIciclePosition);
icicleList.add(newIcicle);
}
for (Icicle icicle : icicleList) {
icicle.update(delta);
}
icicleList.begin();
for (int i = 0; i < icicleList.size; i++) {
if (icicleList.get(i).position.y < -Constants.ICICLES_HEIGHT) {
iciclesDodged += 1;
icicleList.removeIndex(i);
}
}
icicleList.end();
}
public void render(ShapeRenderer renderer) {
renderer.setColor(Constants.ICICLE_COLOR);
for (Icicle icicle : icicleList) {
icicle.render(renderer);
}
}
}
Constant:
package com.udacity.gamedev.icicles;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.math.Vector2;
public static final float ICICLES_HEIGHT = 1.0f;
public static final float ICICLES_WIDTH = 0.5f;
public static final Vector2 ICICLES_ACCELERATION = new Vector2(0,-5.0f);
public static final Color ICICLE_COLOR = Color.WHITE;
I am following a video tutorial on Youtube called "Making Simple Sidescroller with Overlap2D and libGDX - Tutorial - 003".
I see on video he use raycast to detect collision. But when i try to follow, the player fall through the ground while in the video the player can stop on the ground.
Here is the link to download my libgdx project, and my overlap2d project for you to check.
Here is the code of Player.java
package com.test.superninja;
import com.badlogic.ashley.core.Entity;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input;
import com.uwsoft.editor.renderer.scripts.IScript;
import com.uwsoft.editor.renderer.components.TransformComponent;
import com.uwsoft.editor.renderer.components.DimensionsComponent;
import com.uwsoft.editor.renderer.utils.ComponentRetriever;
import com.uwsoft.editor.renderer.physics.PhysicsBodyLoader;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.physics.box2d.Fixture;
import com.badlogic.gdx.physics.box2d.RayCastCallback;
import com.badlogic.gdx.physics.box2d.World;
public class Player implements IScript {
private Entity player;
private TransformComponent transformComponent;
private DimensionsComponent dimensionsComponent;
private Vector2 speed;
private float gravity = -500f;
private float jumpSpeed = 170f;
private World world;
public Player(World world) {
this.world = world;
}
#Override
public void init(Entity entity) {
player = entity;
transformComponent = ComponentRetriever.get(entity, TransformComponent.class);
dimensionsComponent = ComponentRetriever.get(entity, DimensionsComponent.class);
speed = new Vector2(50, 0);
}
#Override
public void act(float delta) {
//transformComponent.scaleY = 0.5;
if (Gdx.input.isKeyPressed(Input.Keys.LEFT)) {
transformComponent.x -= speed.x * delta;
transformComponent.scaleX = -1f;
}
if (Gdx.input.isKeyPressed(Input.Keys.RIGHT)) {
transformComponent.x += speed.x * delta;
transformComponent.scaleX = 1f;
}
if (Gdx.input.isKeyJustPressed(Input.Keys.SPACE)) {
speed.y = jumpSpeed;
}
speed.y += gravity * delta;
transformComponent.y += speed.y * delta;
/*
if (transformComponent.y < 16f){
speed.y = 0;
transformComponent.y = 16f;
}
*/
}
private void rayCast() {
float rayGap = dimensionsComponent.height / 2;
// Ray size is the exact size of the deltaY change we plan for this frame
float raySize = -(speed.y) * Gdx.graphics.getDeltaTime();
//if(raySize < 5f) raySize = 5f;
// only check for collisions when moving down
if (speed.y > 0) return;
// Vectors of ray from middle middle
Vector2 rayFrom = new Vector2((transformComponent.x + dimensionsComponent.width / 2) * PhysicsBodyLoader.getScale(), (transformComponent.y + rayGap) * PhysicsBodyLoader.getScale());
Vector2 rayTo = new Vector2((transformComponent.x + dimensionsComponent.width / 2) * PhysicsBodyLoader.getScale(), (transformComponent.y - raySize) * PhysicsBodyLoader.getScale());
// Cast the ray
world.rayCast(new RayCastCallback() {
#Override
public float reportRayFixture(Fixture fixture, Vector2 point, Vector2 normal, float fraction) {
// Stop the player
speed.y = 0;
// reposition player slightly upper the collision point
transformComponent.y = point.y / PhysicsBodyLoader.getScale() + 0.1f;
return 0;
}
}, rayFrom, rayTo);
}
public float getX() {
return transformComponent.x;
}
public float getY() {
return transformComponent.y;
}
public float getWidth() {
return dimensionsComponent.width;
}
#Override
public void dispose() {
}
}
Here is SuperNinja.java
package com.test.superninja;
import com.badlogic.gdx.ApplicationAdapter;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.GL20;
import com.uwsoft.editor.renderer.SceneLoader;
import com.badlogic.gdx.utils.viewport.Viewport;
import com.badlogic.gdx.utils.viewport.FitViewport;
import com.uwsoft.editor.renderer.utils.ItemWrapper;
import com.uwsoft.editor.renderer.components.additional.ButtonComponent;
import com.badlogic.gdx.graphics.OrthographicCamera;
public class SuperNinja extends ApplicationAdapter {
private SceneLoader sceneLoader;
private Viewport viewport;
private ItemWrapper root;
private Player player;
private UIStage uiStage;
#Override
public void create () {
viewport = new FitViewport(266, 160);
sceneLoader = new SceneLoader();
sceneLoader.loadScene("MainScene", viewport);
root = new ItemWrapper(sceneLoader.getRoot());
player = new Player(sceneLoader.world);
root.getChild("player").addScript(player);
uiStage = new UIStage(sceneLoader.getRm());
}
#Override
public void render () {
Gdx.gl.glClearColor(0.5f, 0.5f, 0.5f, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
sceneLoader.getEngine().update(Gdx.graphics.getDeltaTime());
uiStage.act();
uiStage.draw();
((OrthographicCamera)viewport.getCamera()).position.x=player.getX()+player.getWidth()/2f;
}
}
Here is UIStage.java
package com.uwsoft.platformer;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.scenes.scene2d.Actor;
import com.badlogic.gdx.scenes.scene2d.InputEvent;
import com.badlogic.gdx.scenes.scene2d.Stage;
import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;
import com.badlogic.gdx.scenes.scene2d.utils.ClickListener;
import com.uwsoft.editor.renderer.data.CompositeItemVO;
import com.uwsoft.editor.renderer.data.ProjectInfoVO;
import com.uwsoft.editor.renderer.resources.IResourceRetriever;
import com.uwsoft.editor.renderer.scene2d.CompositeActor;
/**
* Created by azakhary on 8/5/2015.
*/
public class UIStage extends Stage {
public UIStage(IResourceRetriever ir) {
Gdx.input.setInputProcessor(this);
ProjectInfoVO projectInfo = ir.getProjectVO();
CompositeItemVO menuButtonData = projectInfo.libraryItems.get("menuButton");
CompositeActor buttonActor = new CompositeActor(menuButtonData, ir);
addActor(buttonActor);
buttonActor.setX(getWidth() - buttonActor.getWidth());
buttonActor.setY(getHeight() - buttonActor.getHeight());
buttonActor.addListener(new ClickListener() {
#Override
public void clicked (InputEvent event, float x, float y) {
System.out.println("Hi");
}
});
}
}
With the help of Xeon, I solved my question. I just forgot to call rayCast() function.
I call raycast() function like this:
#Override
public void act(float delta) {
...
rayCast();
}
And it works. Thank you Xeon very much.
I'm trying to recreate Space Invaders in LibGDX to get grip on game-developing but when I try to set every enemy (for now they are just squares) to move in sequence the update() method makes them change their postitions way too fast. Is there some way to slow down this rendering on whole project or any other proper way to solve this? I also tried to handle movement in Timer class and scheulde it but it caused memory overload and threads weren't fired in the same time for every object.
package regularmikey.objects;
import java.util.Timer;
import java.util.TimerTask;
import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
import com.badlogic.gdx.graphics.glutils.ShapeRenderer.ShapeType;
public class Aliens {
public float x;
public float y;
public float fx;
public float fy;
public int step_count = 0;
public Aliens(float x, float y) {
this.fx = this.x = x;
this.fy = this.y = y;
};
public void update(float dt){
if(step_count == 10) {
step_count = 0;
y = y - 1;
x = fx;
}
x = x + 3;
step_count++;
};
PlayState class
package regularmikey.gamestates;
import java.util.ArrayList;
import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
import regularmikey.managers.GameStateManager;
import regularmikey.objects.Aliens;
import regularmikey.objects.Bullet;
import regularmikey.objects.Player;
public class PlayState extends GameState {
private Player player;
private ArrayList<Bullet> bullets;
private ArrayList<Aliens> aliens;
private ShapeRenderer sr;
public PlayState(GameStateManager gsm) {
super(gsm);
}
#Override
public void init() {
sr = new ShapeRenderer();
bullets = new ArrayList<Bullet>();
aliens = new ArrayList<Aliens>();
player = new Player(bullets);
spawnAliens();
}
#Override
public void update(float dt) {
player.update(dt);
for(int i = 0; i < aliens.size(); i++) {
aliens.get(i).update(dt);
}
}
public void spawnAliens() {
aliens.clear();
float i, j;
for(j = 100; j <= 510; j = j + 45) {
for(i = 250; i <= 445; i = i + 45) {
aliens.add(new Aliens(j, i));
}
}
}
#Override
public void draw() {
player.draw(sr);
for(int i = 0; i < aliens.size(); i++) {
aliens.get(i).draw(sr);
}
}
#Override
public void handleinput() {
// TODO Auto-generated method stub
}
#Override
public void dispose() {
// TODO Auto-generated method stub
}
}
public void draw(ShapeRenderer sr) {
sr.setColor(1, 1, 1, 1);
sr.begin(ShapeType.Line);
sr.rect(x, y, 30, 30);
sr.end();
};
}
The key here is the dt variable that is passed along with the update() method, which is short for Delta Time.
Delta time is a commonly used factor in game development that represents the time that has passed since the last frame.
I can't exactly make out the way you are making your aliens move about, but the usual way to make entities in your game move smoothly (regardless of the frame rate):
void update(float deltaTime){
this.position = currentPosition + (this.movementSpeed × deltaTime);
}
This doesn't take into consideration the direction in which the entity is moving, amongst others. But that is besides the point of this example.
So, in your case, you could so something like this:
package regularmikey.objects;
import java.util.Timer;
import java.util.TimerTask;
import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
import com.badlogic.gdx.graphics.glutils.ShapeRenderer.ShapeType;
public class Aliens {
public float x;
public float y;
public float fx;
public float fy;
public int step_count = 0;
private float moveTimer;
private float moveTreshold;
public Aliens(float x, float y) {
this.fx = this.x = x;
this.fy = this.y = y;
moveTimer = 0; // This will act as a stopwatch
moveTreshold = 3000; // Alien will move once it passes this treshold
};
public void update(float dt){
// check whether we passed the treshold for moving or not
if(moveTimer += dt; > moveTreshold){
if(step_count == 10) {
step_count = 0;
y = y - 1;
x = fx;
}
x = x + 3;
step_count++;
moveTimer = 0; // reset the timer
}
};
I'm building a little "pong" game in Java.
I'm trying to add a scorekeeper up top that shows the updated score (+1) everytime the player saves the ball with the paddle.
I'm trying to use a JLabel but the problem is that I can't think of a way to continuously update the JLabel each time the paddle is hit.
Any ideas?
My code:
MainPanel Class (the one with the Paddle and Ball and Label)
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
//import swing.graphics.BounceFrame;
//import swing.graphics.Circle;
public class MainPanel extends JPanel implements ActionListener, KeyListener, Runnable{
public Paddle paddle;
public Ball ball;
public MainPanel(){
ball = new Ball(50, 50, 10); //centerX, centerY, radius
setSize(300, 300);
paddle = new Paddle();
JLabel scoreKeeper = new JLabel("Score" + ball.getScore());
add(scoreKeeper);
Thread thread = new Thread(this);
thread.start();
}
public void paint(Graphics g) {
super.paint(g);
Graphics2D g2 = (Graphics2D)g;
paddle.draw(g2);
ball.draw(g2);
}
public void actionPerformed(ActionEvent e) {
String direction = e.getActionCommand();
switch(direction){
case "left": Paddle.movePaddleLeft(); break;
case "right": Paddle.movePaddleRight(); break;
}
this.repaint();
}
public void run() {
try {
while(true){
ball.move(getBounds());
repaint();
Thread.sleep(500/30);
}
}
catch (Exception e) {
e.printStackTrace();
}
}
#Override
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == 37){
Paddle.movePaddleLeft();
}
if (e.getKeyCode() == 39){
Paddle.movePaddleRight();
}
}
#Override
public void keyReleased(KeyEvent e) {
}
#Override
public void keyTyped(KeyEvent e) {
}
}
And my Ball class:
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Rectangle2D;
import java.util.Random;
public class Ball {
private Ellipse2D ball;
private double radius;
private double ballCircumference;
private Color color;
private double x;
private double y;
private double dx = 5;
private double dy = 5;
private int score = 0;
public int getScore() {
return score;
}
//Boundaries to determine if ball is hit by paddle
private double criticalBoundaryX;
private double criticalBoundaryY1;
private double criticalBoundaryY2;
private double paddleHalfwayPoint;
private boolean inGame = true;
public void recalculateCriticals(){
criticalBoundaryX = Paddle.getYPosition() - ballCircumference;
criticalBoundaryY1 = Paddle.getXPosition()- ballCircumference; //Left boundary
criticalBoundaryY2 = Paddle.getXPosition()+Paddle.getPaddleWidth()+ballCircumference; //Right Boundary
paddleHalfwayPoint = (Paddle.getXPosition()+Paddle.getPaddleWidth())/2;
}
public Ball(int centerX, int centerY, int radius) {
this.x = centerX - radius;
this.y = centerY - radius;
this.radius = radius;
ballCircumference = 2*radius;
Random randomRGB = new Random();
color = new Color(randomRGB.nextInt(255), randomRGB.nextInt(255), randomRGB.nextInt(255));
this.ball = new Ellipse2D.Double(x, y, 2*radius, 2*radius);
}
public void move(Rectangle2D bounds) {
recalculateCriticals();
x += dx;
y += dy;
if (x < bounds.getMinX()) {
x = bounds.getMinX();
dx = -dx;
}
if (x + 2*radius >= bounds.getMaxX()) {
//System.out.println(bounds.getMaxX());
x = bounds.getMaxX() - 2*radius;
dx = -dx;
}
if (y < bounds.getMinY()) {
y = bounds.getMinY();
dy = -dy;
}
if (y > criticalBoundaryX){
if (x < criticalBoundaryY1 || x > criticalBoundaryY2){
inGame = false;
}
if (!inGame && hittingEdge(x))
dx = -dx;
}
if (y > criticalBoundaryX && inGame){ //When it hits the paddle
changeColor();
score++;
y = criticalBoundaryX;
dy = -dy;
}
if (y > bounds.getMaxY()){
System.out.println("Game Over");
System.exit(0);
}
recalculateCriticals();
ball.setFrame(x, y, 2*radius, 2*radius);
}
public boolean onPaddle(double x){
return ((x > Paddle.getXPosition()) && (x < Paddle.getXPosition()+Paddle.getPaddleWidth()) && (y > Paddle.getYPosition()-10));
}
public boolean hittingEdge(double x){
return ((x >= criticalBoundaryY1 && x < paddleHalfwayPoint)
||
(x <= criticalBoundaryY1 && x > paddleHalfwayPoint)); //Return true if x is hitting the side edge of the paddle
}
public void changeColor(){
Random randomColor = new Random();
color = new Color(randomColor.nextInt(255), randomColor.nextInt(255), randomColor.nextInt(255));
}
public void draw(Graphics2D g2) {
g2.setColor(color);
g2.fill(ball);
}
}
The "Java way" of doing this would be to define a listener interface, for example:
public interface BallListener {
void paddleHit();
}
In the Ball class, you should add a field
private List<BallListener> listeners;
as well as methods
public void addBallListener(BallListener l) { listeners.add(l); }
public void removeBallListener(BallListener l) { listeners.remove(l); }
When the paddle is hit, you go:
for (BallListener l : listeners)
l.paddleHit();
The main class should implement the BallListener interface, and register itself with the ball (ball.addBallListener(this)).
This approach also enables you to, when needed, inform other parts of your program about different events that happen to the ball (i.e. add a new method to BallListener for each event you'd like to signal).