I want to know how I can make collision happen between the two circles. One of them is movable, as you can see, and I want to make it so that the movable circle can actually push the smaller one. However, I don't want simple rectangle collision. I'm trying to make it so that the circles direction of push depends on the positions of the two circles.
package haex;
import java.applet.*;
import java.awt.*;
import java.awt.event.*;
public class haex extends Applet implements Runnable, KeyListener{
private static final long serialVersionUID = 1L;
int x = 0, y = 0, footballX = 100, footballY = 100;
double angle, xVel, yVel;
Image dbImage;
Graphics dbg;
boolean up, down, left, right, kick;
public void init(){
addKeyListener(this);
}
public void start(){
Thread th = new Thread(this);
th.start();
}
public void run(){
while(true){
angle = Math.atan2((footballX + 12) - (x + 25), (footballY + 12) - (y + 25));
if(Math.sqrt(Math.pow((footballX + 12) - (x + 25), 2) + Math.pow((footballY + 12) - (y + 25), 2)) <= 37){
xVel = Math.cos(angle);
yVel = Math.sin(angle);
footballX += xVel;
footballY += yVel;
}
if(up) y--;
if(down) y++;
if(left) x--;
if(right) x++;
try{Thread.sleep(1000/60);}catch(InterruptedException x){}
repaint();
}
}
public void stop(){}
public void destroy(){}
public void paint(Graphics g){
if(kick){
g.setColor(Color.lightGray);
}else{
g.setColor(Color.black);
}
g.fillOval(x, y, 50, 50);
g.setColor(Color.blue);
g.fillOval(x + 5, y + 5, 40, 40);
g.setColor(Color.black);
g.fillOval(footballX, footballY, 24, 24);
g.setColor(Color.white);
g.fillOval(footballX + 2, footballY + 2, 20, 20);
g.setColor(Color.black);
g.drawLine(x + 25, y + 25, footballX + 12, footballY + 12);
}
public void keyPressed(KeyEvent e){
if(e.getKeyCode() == KeyEvent.VK_UP) up = true;
if(e.getKeyCode() == KeyEvent.VK_DOWN) down = true;
if(e.getKeyCode() == KeyEvent.VK_LEFT) left = true;
if(e.getKeyCode() == KeyEvent.VK_RIGHT) right = true;
if(e.getKeyCode() == KeyEvent.VK_X) kick = true;
}
public void keyReleased(KeyEvent e){
if(e.getKeyCode() == KeyEvent.VK_UP) up = false;
if(e.getKeyCode() == KeyEvent.VK_DOWN) down = false;
if(e.getKeyCode() == KeyEvent.VK_LEFT) left = false;
if(e.getKeyCode() == KeyEvent.VK_RIGHT) right = false;
if(e.getKeyCode() == KeyEvent.VK_X) kick = false;
}
public void update(Graphics g){
if(dbImage == null){
dbImage = createImage(this.getSize().width, this.getSize().height);
dbg = dbImage.getGraphics();
}
dbg.setColor(getBackground());
dbg.fillRect(0, 0, this.getSize().width, this.getSize().height);
dbg.setColor(getForeground());
paint(dbg);
g.drawImage(dbImage, 0, 0, this);
}
#Override
public void keyTyped(KeyEvent e){}
}
Doing circular collision should be even easier than rectangular, just use a single radius for each instead of seperate x and y dimensions. Just calculate if the distance between their center points is less than the radius of both. If so, they're touching, if not, they aren't.
EDIT:
So the problem is calculating the resultant velocities and directions of the balls AFTER collision, not calculating the collision itself? Learn to explain the problem accurately if you want accurate help.
In that case, compare the X values of the two center points and the Y values of the two center points. Collisions should be largely elastic, so if a ball is hit on the left side, it should go to the right side, and vise versa. Then you just have to combine the X and Y components into a vector to get the direction and magnitude of the reaction.
Related
This is my code:
boolean keyPressed = true;
boolean mousePressed = true;
PShape circle;
int x;
int y;
void setup() {
background(0);
fullScreen(1);
frameRate(144);
fill(255, 255, 0);
circle = createShape(ELLIPSE, 0, 0, 50, 50);
}
void draw() {
background(0);
if (mousePressed == true) {
noCursor();
}
if (keyPressed == true && key == 'w') {
x = int(random(width));
y = int(random(height));
rect(x, y, 40, 40);
fill(255, 0, 255);
}
if (key == 's') {
background(0);
}
translate(mouseX, mouseY);
shape(circle);
}
Currently when pressing W the shape appears rapidly. I would like to have it where the shape spawns once, then when the background is cleared and W is pressed again the shape is located somewhere else.
I'm a newbie in Java and I'm trying to make a ship fire a bullet. What I want is actually make the ship fire bullets as long as the Spacebar button is being held down.
I've successfully made the ship move here and there and also fire the bullet. However the bullet just won't go up. Here's my code -
package learningPackage;
import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
public class Draw extends JFrame implements Runnable {
//Variables for the x and y coordinates, xDirection for modifying the values of x only.
int x, y, xDirection;
int bx, by;
Image dbImage;
Graphics dbGraphics;
boolean shot;
Rectangle bullet;
//Thread run
public void run() {
try {
while (true) {
move();
shoot();
//Setting sleep to 0 will make it light-speed!
Thread.sleep(5);
}
}
catch (Exception e) {
System.out.println("Error!");
}
}
//Ship move
//Ship moves only in one direction, x - axis
public void move() {
x += xDirection;
//Collision detection
if (x <= 10) {
x = 10;
}
if (x >= 415) {
x = 415;
}
}
//KeyListeners
public class AL extends KeyAdapter {
public void keyPressed(KeyEvent e) {
int keyCode = e.getKeyCode();
if (keyCode == e.VK_LEFT) {
xDirection = -2;
}
if (keyCode == e.VK_RIGHT) {
xDirection = 2;
}
if (keyCode == e.VK_SPACE) {
shot = true;
}
}
public void keyReleased(KeyEvent e) {
int keyCode = e.getKeyCode();
if (keyCode == e.VK_LEFT) {
xDirection = 0;
}
if (keyCode == e.VK_RIGHT) {
xDirection = 0;
}
if (keyCode == e.VK_SPACE) {
shot = false;
}
}
}
//Constructor for the game frame
public Draw() {
super("Game");
setSize(500, 500);
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setResizable(false);
addKeyListener(new AL());
x = 200;
y = 465;
setVisible(true);
}
//Double - buffering
public void paint(Graphics g) {
dbImage = createImage(getWidth(), getHeight());
dbGraphics = dbImage.getGraphics();
paintComponent(dbGraphics);
g.drawImage(dbImage, 0, 0, this);
}
//All the graphics
public void paintComponent(Graphics g) {
bullet = new Rectangle(bx, by, 10, 10);
g.setColor(Color.RED);
//Ship rectangle
g.fillRect(x, y, 75, 25);
//Gun rectangle
g.fillRect(x + 32, y - 15, 10, 15);
//Setting the same values for bx and by as x and y so that the bullet will start from the Gun rectangle
bx = x + 32;
by = y - 15;
if (shot == true) {
g.setColor(Color.BLACK);
g.fillRect(bx, by, bullet.width, bullet.height);
}
repaint();
}
public void shoot() {
if (shot == true) {
by = by - 2;
}
if (by <= -5) {
//Resetting values
bx = x + 32;
by = y - 15;
bullet = new Rectangle(bx, by, 10, 10);
shot = false;
}
}
//Main method
public static void main(String[] args) {
Draw gameTry = new Draw();
Thread t1 = new Thread(gameTry);
t1.start();
}
}
Here's what happens when I just move the ship, working perfectly fine -
Here's what happens when I hold down space -
(Sorry for not being able to embed pics in the post itself, I'm new to Stack Overflow as well!)
I was actually coping this code from a tutorial but since the tutorial-code wasn't working out, I decided to do this on my own, but I can't do it on my own as well!
Help will definitely be appreciated!
The reason for the bullet not moving becomes appearant when you compare your shoot() method, and the paintComponent method.
Shoot checks if you have the shot boolean set, and if so, moves the bullet y position up by 2.
When the bullet leaves the top of the screen, it resets the "bullet".
This is all fine, it does what it's supposed to.
public void shoot() {
if (shot == true) {
by = by - 2; //this is fine, it moves the bullet up
}
if (by <= -5) {
//Resetting values
bx = x + 32;
by = y - 15;
bullet = new Rectangle(bx, by, 10, 10);
shot = false;
}
}
Then comes paintComponent, which is executed time your game is "painted" to the screen.
It defines a rectangle for the bullet at its current position,
draws the ship,
Then overwrites the bullet's x and y position so it sits on top of the ship.
That is where your problem is
public void paintComponent(Graphics g) {
bullet = new Rectangle(bx, by, 10, 10);
g.setColor(Color.RED);
g.fillRect(x, y, 75, 25);
g.fillRect(x + 32, y - 15, 10, 15);
//you are messing with bx and by here.
//probably because you wanted the bullet to be in the
//same position as the ship.
//this means they will be put back into the same position
//for every time your game is painted to the screen.
//my advice is, do *not* do this here.
bx = x + 32;
by = y - 15;
if (shot == true) {
g.setColor(Color.BLACK);
g.fillRect(bx, by, bullet.width, bullet.height);
}
repaint();
}
Hey guys I am making a game in which characters can be moved with WASD and Arrow keys. I got them to move but i can not make them move at the same time. One can not be moving for the other shape to move. Is there a way to check for WASD and arrow presses simultaneously? Hope you guys can help. Thanks in advance.
Here is the code:
// The "SoccerGame" class.
import java.awt.*;
import java.applet.*;
import java.awt.event.*;
public class SoccerGame extends Applet implements KeyListener
{
//x and y values of the player 1 and 2's character and the ball
int x1 = 0, y1 = 275, x2 = 780, y2 = 275, xBall = 400, yBall = 275;
public void init ()
{
this.requestFocus ();
addKeyListener (this);
//setting size of program
setSize (800, 550);
} // init method
public void paint (Graphics g)
{
//Player 1
g.setColor (Color.red);
g.fillRect (x1, y1, 30, 30);
//Player2
g.setColor (Color.black);
g.fillRect (x2, y2, 30, 30);
//Ball
g.setColor (Color.blue);
g.fillRect (xBall, yBall, 30, 30);
} // paint method
public void keyPressed (KeyEvent e)
{
//Moving Player 1 with arrow Keys
if (e.getKeyCode () == e.VK_W)
{
y1 = y1 - 10;
}
if (e.getKeyCode () == e.VK_S)
{
y1 = y1 + 10;
}
if (e.getKeyCode () == e.VK_A)
{
x1 = x1 - 10;
}
if (e.getKeyCode () == e.VK_D)
{
x1 = x1 + 10;
}
//Moving player 2 with WASD
if (e.getKeyCode () == e.VK_UP)
{
y2 = y2 - 10;
}
if (e.getKeyCode () == e.VK_DOWN)
{
y2 = y2 + 10;
}
if (e.getKeyCode () == e.VK_LEFT)
{
x2 = x2 - 10;
}
if (e.getKeyCode () == e.VK_RIGHT)
{
x2 = x2 + 10;
}
repaint ();
}
public void keyReleased (KeyEvent e)
{
}
public void keyTyped (KeyEvent e)
{
}
} // SoccerGame class
Don't use a KeyListener (as you have been suggested in your other questions).
Instead you should be using Key Bindings. You will then need to track which keys have been pressed and use a Swing Timer to schedule the animation.
Check out Motion Using the Keyboard.
The KeyboardAnimation.java example shows how this can be done.
im creating a 2d world which has a player that is in a rectangle shape and what im trying to do is when the player press space button it draws a block depending on his direction the problem is it only sets for one block and plus it deletes it after repaiting now i know my mistake is in paint method. what i wanna know how to make it draws the block everytime i press space without removing after repainting and can be set for multiple times i know i should use loop but i dont know exactly i should write it
private static final long serialVersionUID = -1401667790158007207L;
int playerx = 450;
int playery = 450;
int playerDirection = 0; //north = 0, west = 1, south = 2, east = 3
boolean setBlock;
public platform(){
super("2D game");
JPanel panel = new JPanel();
panel.setBackground(Color.white);
addKeyListener(this);
this.setContentPane(panel);
}
public void paint(Graphics g){
super.paint(g);
Graphics2D g2 = (Graphics2D)g;
Rectangle player = new Rectangle(playerx, playery, 50, 50);
g2.fill(player);
if(setBlock){
if(playerDirection == 0){
g2.fillRect(playerx, playery - 50, 50, 50);
}else if(playerDirection == 1){
g2.fillRect(playerx + 50, playery, 50, 50);
}else if(playerDirection == 2){
g2.fillRect(playerx, playery + 50, 50, 50);
}else if(playerDirection == 3){
g2.fillRect(playerx - 50, playery, 50, 50);
}
setBlock = false;
}
}
public void keyPressed(KeyEvent e) {
if(e.getKeyCode() == KeyEvent.VK_UP){
playerDirection = 0;
playery -=50;
repaint();
}
if(e.getKeyCode() == KeyEvent.VK_DOWN){
playerDirection = 2;
playery +=50;
repaint();
}
if(e.getKeyCode() == KeyEvent.VK_RIGHT){
playerDirection = 1;
playerx += 50;
repaint();
}
if(e.getKeyCode() == KeyEvent.VK_LEFT){
playerDirection = 3;
playerx -=50;
repaint();
}
if(e.getKeyCode() == KeyEvent.VK_SPACE){
setBlock = true;
}
}
public void keyReleased(KeyEvent e) {
}
public void keyTyped(KeyEvent e) {
}
}
You need to store your Blocks in a List. And add a new one when pressing Space Key. Then you can easily draw all of them in a for loop. Also remove that setBlock boolean because it makes no sense.
...
// introduce this class to hold a block
class Block{
public int x;
public int y;
public Block(int _x, int _y){
x = _x;
y = _y;
}
}
...
// boolean setBlock; // remove this boolean
ArrayList<Block> blocks = new ArrayList<Block>(); // list of all blocks
public platform(){...}
public void paint(Graphics g){
...
// if(setBlock){ // remove this boolean
if(playerDirection == 0){
g2.fillRect(playerx, playery, 50, 50);
}else if(playerDirection == 1){
g2.fillRect(playerx, playery, 50, 50);
}else if(playerDirection == 2){
g2.fillRect(playerx, playery, 50, 50);
}else if(playerDirection == 3){
g2.fillRect(playerx, playery, 50, 50);
}
// draw the blocks
for(Block b : blocks)
g2.fillRect(b.x, b.y, 50, 50);
// setBlock = false; // remove this boolean
//} // remove this boolean
}
public void keyPressed(KeyEvent e) {
...
if(e.getKeyCode() == KeyEvent.VK_SPACE){
// setBlock = true; // remove this boolean
// add a new block
blocks.add(new Block(playerx, playery));
repaint();
}
}
...
This is my code:
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
public class Draw extends JComponent implements KeyListener {
Random r = new Random();
int x = 0;
int y = 0;
int a = 5 * r.nextInt(150);
int b = 5 * r.nextInt(90);
Image img1 = Toolkit.getDefaultToolkit().getImage("C:/Users/Administrator/eclipse/My Projects/Game/src/bluebackground1.png");
public Draw(){
addKeyListener(this);
setFocusable(true);
}
//display
public void paint(Graphics g){
g.drawImage(img1, 0, 0, this);
g.setColor(Color.CYAN);
g.fill3DRect(x, y, 50, 50, true);
g.setColor(Color.RED);
g.draw3DRect(a, b, 50, 50, true);
g.setColor(Color.BLACK);
g.drawLine(0, 500, 800, 500);
g.setColor(Color.BLACK);
g.drawString("Press R to restart the game", 10, 540);
g.drawString("Use arrow keys to move", 600, 540);
if(x == a && y == b){
g.setColor(Color.BLACK);
g.setFont(new Font("", Font.PLAIN, 50));
g.drawString("Victory", 300, 550);
}
}
//controls
public void keyPressed(KeyEvent k) {
if(k.getKeyCode() == KeyEvent.VK_UP){
y -= 5;
} else if(k.getKeyCode() == KeyEvent.VK_DOWN){
y += 5;
} else if(k.getKeyCode() == KeyEvent.VK_LEFT){
x -= 5;
} else if(k.getKeyCode() == KeyEvent.VK_RIGHT){
x += 5;
}
if(k.getKeyCode() == KeyEvent.VK_R){
restart();
}
//border
if(x < 0){
x += 5;
} else if(x > 745){
x -= 5;
} else if(y < 0){
y += 5;
} else if (y > 450){
y -= 5;
}
repaint();
}
public void keyReleased(KeyEvent k) {}
public void keyTyped(KeyEvent k) {}
//restart function
public void restart(){
x = 0;
y = 0;
a = 5 * r.nextInt(150);
b = 5 * r.nextInt(90);
}
}
What I want is when the cyan rectangle which is moveable gets inside the red rectangle which is not moveable the red rectangle disappears permanently because the game is not over and the cyan rectangle will have to move more.
How do I remove the red rectangle when it collides with the cyan one?
Store Shape instances in a List. At time of painting, iterate the list and draw each one. When one shape is removed, remove it from the list and call repaint().