java - collision detection not working? - java

im quite new to java. I am trying to make it so that i can control a ball with the arrow keys and then if you collide with another ball, it will print a line in the console saying "you lost" or somthing.
I have done the moving, but i am struggling a bit with how i can get the 2 balls to collide. so far i have tried this (i think i put a rectangle around the ball, but i don't know really!):
public void collision() {
Rectangle rectP = new Rectangle(player.x, player.y, player.WIDTH, player.HEIGHT);
Rectangle rectE = new Rectangle(Enemy.ex, Enemy.ey, Enemy.WIDTH, Enemy.HEIGHT);
if(rectP.intersects(rectE))
{
System.out.println("game over");
}
}
Could someone help me out and explain what i have done wrong.
ps. please don't just give me the code, i do want to try and learn!!!.
thanks.
public void actionPerformed(ActionEvent e) {
repaint();
x += velx;
y += vely;
}
public void up() {
vely = -1.5;
velx = 0;
}
public void down() {
vely = 1.5;
velx = 0;
}
public void left() {
vely = 0;
velx = -1.5;
}
public void right() {
vely = 0;
velx = 1.5;
}
public void keyPressed(KeyEvent e) {
int code = e.getKeyCode();
if (code == KeyEvent.VK_UP) {
up();
}
if (code == KeyEvent.VK_DOWN) {
down();
}
if (code == KeyEvent.VK_LEFT) {
left();
}
if (code == KeyEvent.VK_RIGHT) {
right();
}
}

If you have coords X and Y of the two ball centers and you know balls radiuses - this should be a simple task.
Just calculate the distance between centers of the balls and compare it with sum of balls radiuses.
You asked to skip formulas so that's it :)
PS What looks strange in your code is that player is lowercased but Enemy is capitalized.. is it a class or an object?

Well, I don't think that what is wrong is the collision detection. I think that what is wrong is that what the computer think that the objects are somewhere else then where they actually are. Like one time when I was trying to make a brickbreaker paddle, I was having problems with collision detection when really the program thought that the paddle was on the opposite side! What you should do is that you should draw the positions of the rectangle onto the game. This way, you can see where the computer thinks the objects are. Maybe they are totally off?

Related

Java smooth movement with KeyEvents in breakout

I'm currently learning Java through Stanford's Programming Methodology (2008) course. I'm trying to create the game Breakout and am trying to currently animate the paddle, which is a GRect type object. Here's my code:
// moves paddle via keyboard
public void keyPressed(KeyEvent e) {
int key = e.getKeyCode();
if (key == KeyEvent.VK_RIGHT && paddle.getX() < getWidth() - paddle.getWidth()) {
paddle.move(5, 0);
}
if (key == KeyEvent.VK_LEFT && paddle.getX() > 0) {
paddle.move(-5, 0);
}
}
//moves paddle via mouse
public void mouseMoved(MouseEvent e) {
while (e.getX() > paddle.getX() + PADDLE_WIDTH/2 && paddle.getX() < getWidth() - PADDLE_WIDTH) {
paddle.move(1, 0);
}
while (e.getX() < paddle.getX() + PADDLE_WIDTH/2 && paddle.getX() > 0) {
paddle.move(-1, 0);
}
The problem is, if I move the paddle with mouse, it follows just fine, it's much smoother than when I try to move it with keyboard. Changing the values in move() method only changes the speed at which the paddle moves.
I've tried googling and one of the things people do is to gradually increase and decrease the speed at which the paddle moves, but I'm not sure how to implement that correctly through this library. Here's my attempt:
private double acceleration(double finalSpeed) {
if (finalSpeed > initialSpeed) {
initialSpeed += delta;
} else if (finalSpeed < initialSpeed) {
initialSpeed -= delta;
}
return initialSpeed;
}
private double initialSpeed = 0;
private double delta = 0.5;
After this I just set the paddle.move(acceleration(5),0) instead of paddle.move (5,0). And I've also added the KeyReleased method that sets the speed to the initial value:
public void keyReleased(KeyEvent e) {
int key = e.getKeyCode();
if (key == KeyEvent.VK_RIGHT || key == KeyEvent.VK_LEFT) {
initialSpeed = 0;
}
However, the movement of the paddle when I switch between left and right arrow keys is not responsive. It has about 0.5 sec delay to start moving the other direction, I've spend whole day trying to figure out the solution but to no avail. Please give me any tips, thanks!
It seems that there's some problem with the threads (which I don't fully understand). Doing this helped:
Instead of moving the paddle directly with listeners, I created two booleans: left_key_downand right_key_down and set them to true if corresponding key was pressed. After that I moved the paddle using: if (left_key_down) move (-5,0) And similarly with right motion. This resulted in smooth motion.

I cannot figure out a way to move the balls

I am currently working on a 3 cushion billiards game project. I have added two balls on the table so far. I am trying to move one of the balls but I am having a hard time doing that. Should I use a timer? If so then could you tell me an effective way to use the timer on my code so I can move my balls?
Your help would be much appreciated.
Thanks in advance.
Farhan Hasan
I have tried to create a move function for the class balls. But I am not sure what I should put inside the function, I have added the xSpeed and ySpeed. The xLocation and the yLocation changes depending on the xSpeed and ySpeed.
public class Balls
{
private Color ballFillColor;
private Color ballBorderColor;
private int ballX = 0;
private int ballY = 0;
private int xSpeed = 5;
private int ySpeed = 0;
private int ballWidth = 0;
private int ballHeight = 0;
Timer t;
public boolean fillBall = false;
private static Balls ballArray[]; //Required for drawMultipleBalls
Balls(){ //Constructor
ballBorderColor = Color.black;
}
Balls(int ballX, int ballY, int ballWidth, int ballHeight, Color ballBorderColor, JFrame window){ //Constructor
// X , Y , Width, Height, Border Colour, container
this.setBallBorderColor(ballBorderColor);
this.setBallWidth(ballWidth);
this.setBallHeight(ballHeight);
this.setBallX(ballX);
this.setBallY(ballY);
this.drawBall(window);
}
//Here is the move function. I am not really sure what to do here.
public void move()
{
if(this.ballX < 1000 - this.ballWidth)
{
this.ballX += this.xSpeed;
}
try
{
Thread.sleep(1);
}
catch(Exception e)
{
}
}
//GET AND SET FUNCTIONS HERE
//HERE ARE THE FUNCTIONS WHICH ARE RESPONSIBLE FOR DRAWING MY BALLS IN JFRAME
public void drawBall(JFrame frame)
{
frame.getContentPane().add(new MyComponent());
}
public void drawMultipleBalls(JFrame frame, Balls[] balls)
{
ballArray = balls;
frame.getContentPane().add(new MyComponent2());
}
private class MyComponent extends JComponent{
public void paintComponent(Graphics g){
if (fillBall) //Fill first, and then draw outline.
{
g.setColor(ballFillColor);
g.fillOval(getBallX(),getBallY(), getBallHeight(),getBallWidth());
}
g.setColor(getBallBorderColor());
g.drawOval(getBallX(),getBallY(), getBallHeight(),getBallWidth());
}
}
private class MyComponent2 extends JComponent{
public void paintComponent(Graphics g){
for (int i = 0; i < ballArray.length; i++)
{
if (ballArray[i].fillBall) //Fill first, and then draw outline.
{
g.setColor(ballArray[i].ballFillColor);
g.fillOval(ballArray[i].getBallX(),ballArray[i].getBallY(), ballArray[i].getBallHeight(),ballArray[i].getBallWidth());
}
g.setColor(ballArray[i].getBallBorderColor());
g.drawOval(ballArray[i].getBallX(),ballArray[i].getBallY(), ballArray[i].getBallHeight(),ballArray[i].getBallWidth());
}
}
}
Hopefully, I can have two movable balls for the game, the should bounce back as the hit the edge of the screen and they should be able to slow down over time. For that, I am thinking to use a damper (I will multiply the xSpeed and ySpeed with a number less than 1, eventually it will slow down the ball)
Here is a simple example I came up with to show a ball moving and bouncing off the edges.
The direction changes based on the boundary. Left and top edges just check for 0. Bottom and right edges need to include the diameter of the ball.
The x and y increments are independent. And these amounts in conjunction with the timer can change the movement. Notice however, that to have objects bounce off of each other (as in a pool game) is more complicated due to angle of trajectories, etc. And the distances bounced will vary and slow with time based on frictional values. Everything else is documented in the Java API.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class MovementDemo extends JPanel implements ActionListener {
JFrame frame = new JFrame("Movement Demo");
int size = 500;
int x = 50;
int y = 200;
int diameter = 50;
int yinc = 2;
int xinc = 2;
int xdirection = 1;
int ydirection = 1;
public MovementDemo() {
setPreferredSize(new Dimension(size, size));
frame.add(this);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> new MovementDemo().start());
}
public void start() {
Timer timer = new Timer(100, this);
timer.setDelay(5);
timer.start();
}
public void actionPerformed(ActionEvent ae) {
if (x < 0) {
xdirection = 1;
}
else if (x > size - diameter) {
xdirection = -1;
}
if (y < 0) {
ydirection = 1;
}
else if (y > size - diameter) {
ydirection = -1;
}
x = x + xdirection * xinc;
y = y + ydirection * yinc;
repaint();
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.setColor(Color.BLUE);
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2d.fillOval(x, y, diameter, diameter);
}
}
It seems in general there are a few things you need to figure out:
has the ball collided with another ball
has the ball collided with a wall
otherwise just figure out what is the ball's new position based on its velocity
Below is some sample code that stubs some of this out. You can first compare the current ball's position to all others (not including the current ball of course). If there are any equal positions, process a collision with a ball. If the ball is at the window border i.e it hit a wall, process a collision with a wall. Otherwise just calculate its new position based on its current velocity.
The process collision part is just to apply physics mechanics to whatever degree of complexity you require. One general suggested change would be to update the velocity of the balls then apply it to the position after. The specific calculations for velocity changes you could apply as needed and as you can imagine it can get pretty involved which is why I suggest using a separate method and possibly a sub class for velocity instead of managing each part of the velocity vector in the ball itself. I used the wall as an object because of this. The composition, weights, velocities etc of the object's colliding can affect the resulting collision, but how complex you want that processing to be is up to you.
Sorry I'm no physics expert but I hope this sends you in the right direction in terms of code! Also this might help with the specific calculations you might want to use:
https://www.khanacademy.org/science/physics/one-dimensional-motion/displacement-velocity-time/v/calculating-average-velocity-or-speed
public void move()
{
// check if balls are on same position not including this ball
for(Ball b: ballArray){
if (this.position == b.position && this != b){
processCollision(this, b, null);
} else{
// if the ball hasn't collided with anything process its movement based on speed
// this assumes a 1000 x 1000 window for keeping objects inside it
if(this.ballX < 1000 - this.ballWidth && this.ballY < 1000 - this.ballHeight){
this.ballX += this.xSpeed;
this.ballY += this.ySpeed;
}else {
processCollision(this, null, new Wall());
}
}
}
try
{
Thread.sleep(1);
}
catch(Exception e)
{
}
}
public void processCollision(Ball b1, Ball b2, Wall w){
// if ball hasn't collided with a wall, process a ball - ball collision
if(w == null){
// apply physics mechanics according the complexity desired for ball collisions
b1.xSpeed -= b2.xSpeed;
b1.ySpeed -= b2.ySpeed;
// ball 2 would end up slowing down
b2.xSpeed -= b1.xSpeed;
b2.ySpeed -= b1.ySpeed;
}
// if ball hasn't collided with a ball, process a ball - wall collision
if(b2 == null){
// apply physics mechanics for hitting a wall
// e.g as below: just send ball in opposite direction
b1.xSpeed = b1.xSpeed * -1;
b1.ySpeed = b1.ySpeed * -1;
}
// either way, process ball's new position based on its new speed
b1.ballX += b1.xSpeed;
b1.ballY += b1.ySpeed;
b2.ballX += b2.xSpeed;
b2.ballY += b2.ySpeed;
}

Shape increases in size instead of moving - Java (GUI applet)

I am trying to change the y position of the rectangle, however, whenever I try to, it expands/gets bigger vertically.
public class PlayerPaddle implements Paddle {
double yVelocity;
final double GRAVITY = 0.94;
//move up/down faster (if not accelerating = slow down)
boolean upAccel, downAccel;
//determines if player 1 or player 2 (on left or on right)
int player;
//position of actual paddle
int x;
double y;
Rectangle panel;
public PlayerPaddle(int player) {
upAccel = false;
downAccel = false;
y = 210; //not moving initially
yVelocity = 0;
if (player == 1) {
//left side
x = 20;
} else {
//right side
x = 660;
}
}
#Override
public void draw(Graphics g) {
//draw paddle
g.setColor(Color.WHITE);
g.fillRect(x, (int) y, 20, 80);
}
#Override
public void move() {
if (upAccel) {
yVelocity -= 2;
} else if (downAccel) {
yVelocity += 2;
} else if ((!upAccel) && (!downAccel)) {
yVelocity *= GRAVITY;
}
y += yVelocity; //changes y position of paddle
}
public void setUpAccel(boolean input) {
upAccel = input;
}
public void setDownAccel(boolean input) {
downAccel = input;
}
#Override
public int getY() {
return (int) y;
}
}
I want to know how to make the rectangle move up and down vertically. A similar question had only one answer which said that the previously painted rectangle was not being cleared and as a result is expanding. But even when I say g.clearRect(...) it still expands and does not move.
I am new to Swing and Awt but I am really committed to learning. Thanks for the help.
A similar question had only one answer which said that the previously painted rectangle was not being cleared and as a result is expanding
And that is still probably the problem here.
Somewhere, not in the code presented here, you need to invoke the draw(...) method of this class.
So in that code you need to make sure the background of the component is cleared before you draw the paddle. Since you should be overriding the paintComponent(...) method of a panel to do custom painting your code should look something like:
#Override
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
// draw the paddle
}
Read the section from the Swing tutorial on Custom Painting for more information and working examples.
I am new to Swing and Awt but I am really committed to learning.
Then keep a link to the tutorial handy for all Swing basics.

Adding a new player with keys WASD

I am really new to programming. For my class, I am making a game and I would like to add a seconds player to the game. At the moment, there are black circles that appear randomly in the game and keep growing. You are a circle and you need to avoid the circles for as long as possible. Once you intersect with one the game ends. This circle is controlled with the arrow keys. However I would like to add a new circle with the keys WASD. This is my code so far. But when the game starts I can see the circle but I cannot move it.
The main part of the code I am worried about is ProcessUserInput2 because that is the code that controls WASD. I have not pasted in my entire code. Any help would be much appreciated
void draw()
{
//Call functions
if (gameState == 0)//Start Screen
{
ProccessUserInput_Start(); //this function is in a separate tab. It processes what the player inputs into the computer, and then translates it into commands
Render_Start();
savedTime = millis();
}
if (gameState == 1)//Game Playing Screen
{
ProcessUserInput1(); //this is for the arrow keys
ProcessUserInput2(); //this is for WASD
Render();
totalTime = 40000; //Timer (in millis)
for (growingEllipse e:ellipses)
{
e.ellipseGrow();
e.rendering();
}
void ProcessUserInput1()
//Move circle Left, Right, Up or Down using arrow keys
{
if (keyPressed)
{
if (keyCode == LEFT)//Move Left
{
x1 = x1 - 2;
}
if (keyCode == RIGHT)//Move Right
{
x1 = x1 + 2;
}
if (keyCode == UP)//Move Up
{
y1 = y1 - 2;
}
if (keyCode == DOWN)//Move Down
{
y1 = y1 + 2;
}
}
}
void ProcessUserInput2()
//Move circle Left, Right, Up or Down using arrow keys
{
if (keyPressed)
{
if (keyCode == 'A')//Move Left
{
x2 = x2 - 2;
}
if (keyCode == 'D')//Move Right
{
x2 = x2 + 2;
}
if (keyCode == 'W')//Move Up
{
y2 = y2 - 2;
}
if (keyCode == 'S')//Move Down
{
y2 = y2 + 2;
}
}
}
void Render()
{
background(255);
fill(255, 228, 196);
ellipse (x1, y1, r1, r1);
ellipse (x2, y2, r1, r1);
//draw circle for player
}
If possible, could any really good programmers give me their email so that I can ask them questions? I still need to add in a few more items such as inheritance and function overloading. I used the Processing application for this.
You're using the keyCode variable, which only works with things like the arrow keys that don't have associated characters.
Instead, you might want to use the key variable, which is a char and contains the character typed.
More info here: http://staticvoidgames.com/tutorials/intermediateConcepts/keyboardInput
Edit: Also, as Jordi said, you're only catching upper-case letters. And please don't ask for email, as that defeats the whole point of public sites like this.

fixed timer and random direction

Hello as a starting Java programmer I am busy creating a simple Pacman game in Java just to exercise and I have created a method for the ghost to move randomly horizontal of vertical but I have a few problems with it I don't know how to force it to go left-right or up-down (so not at the same time) my code for the ghost right now is as follows:
public void moveUp() {
}
public void moveLeft() {
if (g1x >= 500) { g1x = 500; g1r = false; }
else if (g1x <= 0) { g1x = 0; g1r = true; }
}
public void moveRight() {
if (g1x >= 500) { g1x = 500; g1r = false; }
else if (g1x <= 0) { g1x = 0; g1r = true; }
}
public void moveDown() {
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
// pacman movement
diameter = 25;
pacman.drawPacMan(g, getHorPlaats(), getVerPlaats(), diameter, getView(), Color.yellow);
// ghosts movement
g1x += ghostSpeed * (Math.random() > 0.5? 1 : -1); // random direction
Random randomGen = new Random();
// generate a random number, between 0 - 3
int randomize = randomGen.nextInt(4);
switch(randomize) {
case 0:
moveUp();
System.out.println("up");
break;
case 1:
moveLeft();
System.out.println("Left");
break;
case 2:
moveRight();
System.out.println("Right");
break;
case 3:
moveDown();
System.out.println("down");
break;
}
ghost.drawGhost(g, randomize, 40, diameter, Color.red);
}
I have used the randomize variable for the direction as you can see and the horizontal position is hardcoded but the horizontal position is also stated by randomize but if I use it for both it makes some weird diagonal movements
the next problem is that i use a timer in my construction like this
public PacMan() {
// create timer and start timer
javax.swing.Timer autoKlik = new javax.swing.Timer(WACHTTIJD, this);
autoKlik.start();
}
so the random values for the directions is changing to fast ( 500ms ) but the speed also configures the gameplay speed so I think I made a logical mistake but Im not sure how to solve this.. do I have to seperate the actions maybe? or is there a easier way to achieve this please share your skills with me I am motivated to learn :) and if you might need more code I could post it here or give a link to my github account so you can check it out :)
Thanks in advance!
link to the full source: pacman game source
I suggest to separate the concerns:
a set of classes to model the simulation contains only the entities and the logic
a set of graphic classes which draw the pacman
a controller to handle actions and delegate them to the model, fired by the swing classes
In paint() method, for performance reason, do only the painting, NEVER 'new' nor call complex methods. Paint are called very often by the framework.

Categories

Resources