Here is a program that has a ball drop and bounce from wherever the mouse is clicked. Would anyone know how to change the rate that the ball drops to the force of gravity?
Im trying to figure out the proper solution to this... but i am having a little trouble. All help and or input would be much appreciated.
float x;
float y;
float yspeed = 0;
float xspeed = 0;
float balldiameter = 10;
float ballradius = balldiameter/2;
void setup() {
size (400,400);
background (255);
fill (0);
ellipseMode(CENTER);
smooth();
noStroke();
x = width/2;
y = height/2;
}
void draw() {
mouseChecks();
boundaryChecks();
ballFunctions();
keyFunctions();
}
void mouseChecks() {
if (mousePressed == true) {
x = mouseX;
y = mouseY;
yspeed = mouseY - pmouseY;
xspeed = mouseX - pmouseX;
}
}
void boundaryChecks() {
if (y >= height - ballradius) {
y = height - ballradius;
yspeed = -yspeed/1.15;
}
if (y <= ballradius) {
y = ballradius;
yspeed = -yspeed/1.35;
}
if (x >= width -ballradius) {
x = width -ballradius;
xspeed = -xspeed/1.10;
}
if (x <= ballradius) {
x = ballradius;
xspeed = -xspeed/1.10;
}
}
void ballFunctions() {
if (balldiameter < 2) {
balldiameter = 2;
}
if (balldiameter > 400) {
balldiameter = 400;
}
ballradius = balldiameter/2;
background(255); //should this be in here?
ellipse (x,y,balldiameter,balldiameter);
yspeed = yspeed += 0.2;
xspeed = xspeed/1.005;
y = y + yspeed;
x = x + xspeed;
}
void keyFunctions() {
if (keyPressed) {
if(keyCode == UP) {
balldiameter +=1;
}
if (keyCode == DOWN) {
balldiameter -=1;
}
}
}
The acceleration of gravity on earth is 9.81 m/s^2. So, if your ball's velocity is 0 at the point the mouse is clicked, the final velocity will be the acceleration integrated in relation to time. This would be (9.81 * t) / 2. Where t is in seconds. The resulting units would be m/sec. You would have to convert meters to some screen space unit for drawing.
Related
I am making a game in libGDX and I am having trouble setting up the Bullet class. I am unable to get the projectiles to go to the mouse location.
I have tried to use Math.atan() to find the angle that I need to fire at but I couldn't get that to work. right now I am just using the distance to find velocity on the x and y-axis.
private static final int SPEED = 500;
private static Texture texture;
String path = "C:\\Users\\minicodcraft\\Downloads\\game\\core\\assets\\";
private float x, y; // starting position
private float xVelocity, yVelocity;
private float yPos; // the y position of the mouse input
private float xPos; // the x position of the mouse input
public Bullet(float x, float y, float yPos, float xPos) {
this.x = x;
this.y = y;
this.xPos = xPos;
this.yPos = yPos;
this.xVelocity = 0f;
this.yVelocity = 0f;
calcDirection();
if (texture == null) {
texture = new Texture(path + "Bullet.png");
}
}
private void calcDirection() {
float xDistanceFromTarget = Math.abs(xPos - x);
float yDistanceFromTarget = Math.abs(yPos - y);
float totalDistanceFromTarget = xDistanceFromTarget + yDistanceFromTarget;
xVelocity = xDistanceFromTarget / totalDistanceFromTarget;
yVelocity = yDistanceFromTarget / totalDistanceFromTarget;
if (xPos < x) {
xVelocity *= -1;
}
if (yPos < y) {
yVelocity *= -1;
}
}
public void update(float deltaTime) {
if (x > 0 && y > 0) {
x += xVelocity * SPEED * deltaTime;
y += yVelocity * SPEED * deltaTime;
} else if (x < 0 && y > 0) {
x -= xVelocity * SPEED * deltaTime;
y += yVelocity * SPEED * deltaTime;
} else if (x > 0 && y < 0) {
x += xVelocity * SPEED * deltaTime;
y -= yVelocity * SPEED * deltaTime;
} else if (x < 0 && y < 0) {
x -= xVelocity * SPEED * deltaTime;
y -= yVelocity * SPEED * deltaTime;
}
}
public void render(SpriteBatch batch) {
batch.draw(texture, x, y);
}
The following code gives a velocity towards the mouse position from the player's position:
float diffX = mouse.x - player.x;
float diffY = mouse.y - player.y;
float angle = (float) Math.atan2(diffY, diffX);
float velX = (float) (Math.cos(angle));
float velY = (float) (Math.sin(angle));
Vector2 velocity = new Vector2(velX, -velY);
velocity.nor();
velocity.scl(magnitudeSpeed);
velocity.scl(deltaTime);
Then velocity.x is the x component of the velocity. Respective for y. No need to multiply by speed and deltaTime again, already done above.
I can't get around this problem. I've created this frame and panel with my desired output. Only thing is that I haven't been able to figure out was how to make the ball move "automatically". My ideal game would have the ball/circle dropping at the start of the game, perhaps with a click of a button or such. How would I go about doing this?
I've tried to move the ball with the E key, but that would be too inconvenient for the user, so I figured that having it move without an event handler would be a better choice.
private int ballX, ballY, ballR;
private int score1, score2;
private JPanel panel;
private JFrame frame;
private DrawingArea canvas;
private int xpos, ypos,width,height;
private int xpos2, ypos2, width2, height2;
public Pong(){
xpos = 300;
ypos = 550;
width = 100;
height = 50;
xpos2 = 300;
ypos2 = 100;
width2 = 100;
height2 = 50;
ballR = 50;
ballX = 325;
ballY = 330;
}
public static void main(String[]args){
Pong p = new Pong();
p.run();
}
public void run(){
frame = new JFrame("Pong");
frame.setSize(700,700);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
canvas = new DrawingArea(); // create a panel to draw on
canvas.setBackground(Color.WHITE);
canvas.addFocusListener(this);
canvas.addKeyListener(this);
canvas.addMouseListener(this);
frame.getContentPane().add(canvas);
frame.setVisible(true);
}
class DrawingArea extends JPanel {
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor ( Color.blue );
g.fillRect ( xpos, ypos, width, height );
g.setColor(Color.red);
g.fillRect(xpos2, ypos2, width2, height2);
g.setColor(Color.black);
g.fillRect(0,0,700,50);
g.fillRect(0,630,700,50);
g.fillOval(ballX,ballY,ballR, ballR);
}
}
public void keyPressed ( KeyEvent e ) {
int value = e.getKeyCode();
switch ( value ) {
case KeyEvent.VK_RIGHT: xpos += 50; break;
case KeyEvent.VK_LEFT: xpos -= 50; break;
case KeyEvent.VK_A: xpos2 -= 50; break;
case KeyEvent.VK_D: xpos2 += 50; break;
/*try to drop the ball with the space button
* case KeyEvent.VK_SPACE:
ballX+=25;
ballY+=25;
break;
case KeyEvent.VK_ENTER:
xpos = (int)( Math.random ( ) * ( 500 - (2 * radius) ) );
ypos = (int)( Math.random ( ) * ( 500 - (2 * radius) ) );
break;
*/
}
if( (xpos < 0 || xpos >= 700) || (xpos2 < 0 || xpos2 >= 700)){
if(xpos < 0 || xpos2 < 0){
if(xpos < 0) xpos = 0;
else if(xpos2 < 0) xpos2 = 0;
return;
}
else if(xpos >= 700 || xpos2 >= 700){
if(xpos >= 700)xpos = 550;
else if(xpos2 >= 700) xpos2=550;
return;
}
}
canvas.repaint ( );
}
}
I expect the output to have the ball drop down on to the blue rectangle with the start of the game/press of a button, but I can't get that to work.
As you want to move the ball automatically, in run() method change position of the ball(Your xpos, ypos, xpos1 and ypos2) with some increment values(as you have done in keyPressed() interface method) dx, dy etc. and invoke repaint() method of your JFrame.
public class BouncingBall extends JPanel {
// Box height and width
int width;
int height;
// Ball Size
float radius = 40;
float diameter = radius * 2;
// Center of Call
float X = radius + 50;
float Y = radius + 20;
// Direction
float dx = 3;
float dy = 3;
public BouncingBall() {
Thread thread = new Thread() {
public void run() {
while (true) {
width = getWidth();
height = getHeight();
X = X + dx ;
Y = Y + dy;
if (X - radius < 0) {
dx = -dx;
X = radius;
} else if (X + radius > width) {
dx = -dx;
X = width - radius;
}
if (Y - radius < 0) {
dy = -dy;
Y = radius;
} else if (Y + radius > height) {
dy = -dy;
Y = height - radius;
}
repaint();
try {
Thread.sleep(50);
} catch (InterruptedException ex) {
}
}
}
};
thread.start();
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.BLUE);
g.fillOval((int)(X-radius), (int)(Y-radius), (int)diameter, (int)diameter);
}
public static void main(String[] args) {
JFrame.setDefaultLookAndFeelDecorated(true);
JFrame frame = new JFrame("Bouncing Ball");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(300, 200);
frame.setContentPane(new BouncingBall());
frame.setVisible(true);
}
}
As I have used render time of 50 ms in Thread.sleep(), you can specify your own time. So for me each 50 ms your JFrame gets updated.
Most learned friends
I have a sprite that moves around on screen but at the moment it just moves diagonally from left to right and goes off screen and then comes back on the other side.
What I would like it to do is bounce off the edges of the screen in a random fashion but, not being all that clued up on maths, I'm struggling to figure out the coordinates to do this.
Below is what I have so far: (this is an updated code for the Sprite class:
public class Sprite {
//x,y position of sprite - initial position (0,50)
// int [] DIRECTION_TO_ANIMATION_MAP = {3, 1, 0, 2};
private static final int BMP_ROWS = 3;
private static final int BMP_COLUMNS = 4;
private int x = 0;
private int y = 0;
private int xSpeed = 5;//Horizontal increment of position (speed)
private int ySpeed;// Vertical increment of position (speed)
private int currentFrame = 0;
private GameView gameView;
private Bitmap spritebmp;
//Width and Height of the Sprite image
private int bmp_width;
private int bmp_height;
// Needed for new random coordinates.
//private Random random = new Random();
public Sprite(GameView gameView) {
this.gameView = gameView;
spritebmp = BitmapFactory.decodeResource(gameView.getResources(),
R.drawable.running_ninja_sprite);
this.bmp_width = spritebmp.getWidth() / BMP_COLUMNS;
this.bmp_height = spritebmp.getHeight() / BMP_ROWS;
/*Random rnd = new Random(System.currentTimeMillis());
xSpeed = rnd.nextInt(45)-5;
ySpeed = rnd.nextInt(25)-5;*/
}
//update the position of the sprite
public void update() {
//if (x < 0 || x > gameView.getWidth() ){ xSpeed = xSpeed * -1;}
//if (y < 0 || y > gameView.getHeight() ){ ySpeed = ySpeed * -1;}
if (x > gameView.getWidth() - bmp_width - xSpeed || x + xSpeed < 0) {
xSpeed = -xSpeed;
}
x = x + xSpeed;
if (y > gameView.getHeight() - bmp_height - ySpeed || y + ySpeed < 0) {
ySpeed = -ySpeed;
}
y = y + xSpeed;
currentFrame = ++currentFrame % BMP_COLUMNS;
//y = random.nextInt(gameView.getWidth());
//wrapAround(); //Adjust motion of sprite.
}
public void draw(Canvas canvas) {
update();
int srcX = currentFrame * bmp_width;
int srcY = 1 * bmp_height; //getAnimationRow()
Rect src = new Rect(srcX, srcY, srcX + bmp_width, srcY + bmp_height);
Rect dst = new Rect(x, y, x + bmp_width, y + bmp_height);
//Draw sprite image
canvas.drawBitmap(spritebmp, x, y, null);
}
/*private int getAnimationRow() {
double dirDouble = (Math.atan2(xSpeed, ySpeed) / (Math.PI / 2) + 2);
int direction = (int) Math.round(dirDouble) % BMP_ROWS;
return DIRECTION_TO_ANIMATION_MAP[direction];
}*/
public void wrapAround() {
//Code to wrap around
if (x < 0) x = x + gameView.getWidth(); //increment x whilst not off screen
if (x >= gameView.getWidth()) { //if gone of the right sides of screen
x = x - gameView.getWidth(); //Reset x
}
if (y < 0) y = y + gameView.getHeight();//increment y whilst not off screen
if (y >= gameView.getHeight()) {//if gone of the bottom of screen
y -= gameView.getHeight();//Reset y
}
}
// Checks if the sprite was touched
public boolean wasItTouched(float ex, float ey) {
boolean touched = false;
if ((x <= ex) && (ex < x + bmp_width) &&
(y <= ey) && (ey < y + bmp_height)) {
touched = true;
}
return touched;
}
}
It now does bounce off the edge but from top left, diagonally to the right and back up in the same direction and continues to do this back and forth. I'd like it to be random in its direction after hitting the edge. Any suggestions? As you can see from the code I have tried a lot of things but the sprite just keeps on doing this continuous back and forth diagonal motion and I'm at a loss as to what I can do.
Thanks
Just negate your speed every time you hit a wall
if (x < 0 || x > gameView.getWidth() ){ xSpeed = xSpeed * -1;}
if (y < 0 || y > gameView.getHeight() ){ ySpeed = ySpeed * -1;}
/////////////////////////////// Edit
It will fit something like this. You can also remove your wrap function as it is no longer applicable
//update the position of the sprite
public void update() {
x = x + xSpeed;
y = y + xSpeed;
bounce();
}
private void bounce(){
if (x <= 0 || x >= gameView.getWidth() ){ xSpeed = xSpeed * -1;}
if (y <= 0 || y >= gameView.getHeight() ){ ySpeed = ySpeed * -1;}
}
I am currently working on a 2D side scroller and have implemented the techniques use in this article for a grapple hook, and it works really well. My problem is I want my player to be able to swing around the rope a little bit to gain a bit of momentum, but currently I can't stop the player from moving all the way up to 90 degrees either side. What techniques can be applied to force this limit?
I have tried using a separate player speed for swinging but this only slows the process down I can still swing up to 90 deg each side.
Here's my update function in the player
public void update(float dt){
//handle friction and air resistance
if(dx !=0){
if(touchingGround) {
// apply friction
if (dx > 0) {
dx -= retardation;
} else {
dx += retardation;
}
} else {
//applied air resistance
if (dx > 0) {
dx -= airResistance;
} else {
dx += airResistance;
}
}
}
// handle gravity
dy -= Constants.GRAVITY * dt;
if(dy < -terminalVelocity){
dy = -terminalVelocity;
}
/*
Handle Player movement
*/
if(right){
if(dx <= maxSpeed){
dx += acceleration;
}
dx = maxSpeed;
}
if(left){
if(dx <= -maxSpeed){
dx -= acceleration;
}
dx = -maxSpeed;
}
if(isGrappling){
//If we collide with something we need to stop grappling
if(hasCollided){
isGrappling = false;
} else {
// This algorithm from here:
// http://gamedev.stackexchange.com/questions/61596/player-rope-swing
float currentD = (float) Math.sqrt(((grappleX - x) * (grappleX - x)) + ((grappleY - y) * (grappleY - y)));
float prevX = getX(), prevY = getY();
if (currentD > grappleRadius) {
Vector2 hookPos = new Vector2(grappleX, grappleY);
Vector2 testPos = (new Vector2(x, y).sub(hookPos)).nor();
y = (hookPos.y + testPos.y * grappleRadius);
x = (hookPos.x + testPos.x * grappleRadius);
// s = d / t
dx += (x - prevX) / dt;
dy += (y - prevY) / dt;
}
}
}
/*
Collision Detection, handle last always!
*/
float oldX = getX(), oldY = getY();
boolean collisionX = false, collisionY = false;
// move on x
x += dx * dt;
// calculate the increment for step in #collidesLeft() and #collidesRight()
increment = collisionLayer.getTileWidth();
increment = getWidth() < increment ? getWidth() / 2 : increment / 2;
if(dx < 0) // going left
collisionX = collidesLeft();
else if(dx > 0) // going right
collisionX = collidesRight();
// react to x collision
if(collisionX) {
setX(oldX);
dx = 0;
}
// move on y
y += dy * dt;
// calculate the increment for step in #collidesBottom() and #collidesTop()
increment = collisionLayer.getTileHeight();
increment = getHeight() < increment ? getHeight() / 2 : increment / 2;
if(dy < 0) {
touchingGround = collisionY = collidesBottom();
// we can only jump 2 times before we have to touch the floor again
if(collisionY){
numberOfJumps = 2;
}
} else if(dy > 0) {
collisionY = collidesTop();
}
// react to y collision
if(collisionY) {
setY(oldY);
dy = 0;
}
hasCollided = collisionX || collisionY;
}
As I am not using any physics engine I chose to just emulate the physics by limiting the angle at which the player can apply force to the swing.
// check if angle permits movement
if(grappleAngle < Math.PI/9 && grappleAngle > -Math.PI/9) {
// handle momentum gaining on rope
if (right) {
dx += swingAcceleration * dt;
}
if (left) {
dx -= swingAcceleration * dt;
}
}
I have an image inside the panel and it moves in a clockwise direction. Now, I want it to move in a random direction and that is my problem.
Could someone give me an idea how to do it?
Here's what I've tried :
private int xVelocity = 1;
private int yVelocity = 1;
private int x, y;
private static final int RIGHT_WALL = 400;
private static final int UP_WALL = 1;
private static final int DOWN_WALL = 400;
private static final int LEFT_WALL = 1;
public void cycle()
{
x += xVelocity;
if (x >= RIGHT_WALL)
{
x = RIGHT_WALL;
if (y >= UP_WALL)
{
y += yVelocity;
}
}
if (y > DOWN_WALL)
{
y = DOWN_WALL;
if (x >= LEFT_WALL)
{
xVelocity *= -1;
}
}
if (x <= LEFT_WALL)
{
x = LEFT_WALL;
if (y <= DOWN_WALL)
{
y -= yVelocity;
}
}
if (y < UP_WALL)
{
y = UP_WALL;
if (x <= RIGHT_WALL)
{
xVelocity *= -1;
}
}
}
Call a method like this to set a random direction:
public void setRandomDirection() {
double direction = Math.random()*2.0*Math.PI;
double speed = 10.0;
xVelocity = (int) (speed*Math.cos(direction));
yVelocity = (int) (speed*Math.sin(direction));
}
Just noticed that you're cycle method will need a little fixing for this to work.
public void cycle() {
x += xVelocity;
y += yVelocity; //added
if (x >= RIGHT_WALL) {
x = RIGHT_WALL;
setRandomDirection();//bounce off in a random direction
}
if (x <= LEFT_WALL) {
x = LEFT_WALL;
setRandomDirection();
}
if (y >= DOWN_WALL) {
y = DOWN_WALL;
setRandomDirection();
}
if (y <= UP_WALL) {
y = UP_WALL;
setRandomDirection();
}
}
(It works, but this is not the most efficient/elegant way to do it)
And if you want some sort of 'random walk' try something like this:
public void cycle() {
//move forward
x += xVelocity;
y += yVelocity;
if (Math.random() < 0.1) {//sometimes..
setRandomDirection(); //..change course to a random direction
}
}
You can increase 0.1 (max 1.0) to make it move more shaky.
Change
y -= yVelocity;
To
if (y>0) {
y = -1*Random.nextInt(3);
} else {
y = Random.nextInt(3);
}