Angle Question

I'm writing a program for a Pong-like game, but I'm having trouble with the angles. I'm using two variables: XSpeed and YSpeed, for the ball, and every timestep I add XSpeed to XPos and YSpeed to YPos, then I redraw the ball using the statement Draw.fillOval(XPos-Radius, YPos-Radius, Radius*2, Radius*2);--where Radius is the radius of the circle that is the ball, and Draw is an instance of the Graphics class. I have a method ChangeAngle() that randomly generates values for XSpeed and YSpeed. This is called whenever the ball bounces off of something, such as the top and bottom walls or a paddle. Anyway, the problem comes in when trying to make the ball move at approximately the same speed, regardless of what angle it's moving at. I attempted to solve this problem using square roots, such as Math.sqrt(MaxSpeed);, where MaxSpeed is XSpeed when YSpeed==0, or YSpeed when XSpeed==0. Unfortunately, this only works for 45-degree angles and straight lines. So... can someone either provide me with algorithms for other angles (I'd like to have as many potential angles as possible), or perhaps give me a better solution to the problem? Thanks. ^_^

EDIT: If it helps, here's the complete code of the program so far... it's not fully implemented, so a bunch of the instance variables don't do anything yet, and you'll probably find some random methods floating around.

import java.util.*;

import java.awt.*;

import java.applet.*;

import javax.swing.*;

publicclass Bounceextends Appletimplements Runnable

{

int

XPos,

YPos,

Pad1XPos,

Pad1YPos,

Pad2XPos,

Pad2YPos,

XSpeed=9,

YSpeed=9,

PaddleSpeed,

Radius=8,

PaddleHeight=50,

PaddleWidth=10,

MaxSpeed=4;

Image

ImageGen;

Graphics

DBG;

Random

Rand=new Random();

Color

BallColor=new Color(Rand.nextInt(256), Rand.nextInt(256), Rand.nextInt(256)),

Pad1Color=new Color(Rand.nextInt(256), Rand.nextInt(256), Rand.nextInt(256)),

Pad2Color=new Color(Rand.nextInt(256), Rand.nextInt(256), Rand.nextInt(256));

publicvoid start()

{

setBackground(new Color(Rand.nextInt(256), Rand.nextInt(256), Rand.nextInt(256)));

Thread Ball=new Thread(this);

Ball.start();

XPos=this.getWidth()/2;

YPos=this.getHeight()/2;

Pad1XPos=10;

Pad1YPos=this.getHeight()/2;

Pad2XPos=this.getWidth()-10;

Pad2YPos=this.getHeight()/2;

PaddleSpeed=MaxSpeed+1;

ChangeAngle();

}

publicvoid run()

{

Thread.currentThread().setPriority(Thread.MIN_PRIORITY);

while(true)

{

repaint();

try

{

Thread.sleep(10);

}

catch(InterruptedException ex)

{

}

Thread.currentThread().setPriority(Thread.MAX_PRIORITY);

if((XPos-Radius<=0&&XSpeed<0)||(XPos+Radius>=this.getWidth()&&XSpeed>0))

{

XSpeed*=-1;

ChangeAngle();

}

if((YPos-Radius<=0&&YSpeed<0)||(YPos+Radius>=this.getHeight()&&YSpeed>0))

{

YSpeed*=-1;

ChangeAngle();

}

XPos+=XSpeed;

YPos+=YSpeed;

}

}

publicvoid update(Graphics Draw)

{

if(ImageGen==null)

{

ImageGen=createImage(this.getSize().width, this.getSize().height);

DBG=ImageGen.getGraphics();

}

DBG.setColor(getBackground());

DBG.fillRect(0, 0, this.getSize().width, this.getSize().height);

DBG.setColor(getForeground());

paint(DBG);

Draw.drawImage(ImageGen, 0, 0,this);

}

publicvoid paint(Graphics Draw)

{

Draw.setColor(BallColor);

Draw.fillOval(XPos-Radius, YPos-Radius, Radius*2, Radius*2);

Draw.setColor(Pad1Color);

Draw.fillRect(Pad1XPos-(PaddleWidth/2), Pad1YPos-(PaddleHeight/2), PaddleWidth, PaddleHeight);

Draw.setColor(Pad2Color);

Draw.fillRect(Pad2XPos-(PaddleWidth/2), Pad2YPos-(PaddleHeight/2), PaddleWidth, PaddleHeight);

Draw.setColor(new Color(Rand.nextInt(256), Rand.nextInt(256), Rand.nextInt(256)));

Draw.drawString("XSpeed: "+XSpeed, 125, 225);

Draw.drawString("YSpeed: "+YSpeed, 375, 225);

}

publicboolean keyDown(Event e,int key)

{

returntrue;

}

publicvoid ChangeAngle()

{

int Num;

XSpeed/=Math.abs(XSpeed);

YSpeed/=Math.abs(YSpeed);

Num=Rand.nextInt(6);

switch(Num)

{

case 0: XSpeed*=Math.sqrt(MaxSpeed); YSpeed*=Math.sqrt(MaxSpeed);break;

case 1: XSpeed*=Math.sqrt(MaxSpeed); YSpeed*=-Math.sqrt(MaxSpeed);break;

case 2: XSpeed*=Math.sqrt(MaxSpeed); YSpeed*=Math.sqrt(MaxSpeed)/2;break;

case 3: XSpeed*=Math.sqrt(MaxSpeed); YSpeed*=-Math.sqrt(MaxSpeed)/2;break;

case 4: XSpeed*=Math.sqrt(MaxSpeed)/2; YSpeed*=Math.sqrt(MaxSpeed);break;

case 5: XSpeed*=Math.sqrt(MaxSpeed)/2; YSpeed*=-Math.sqrt(MaxSpeed);break;

}

}

}

[7651 byte] By [Fenrisa] at [2007-11-27 4:19:56]
# 1

// <applet code="BounceApplet" width="400" height="400"></applet>

import java.awt.*;

import java.awt.geom.Ellipse2D;

import java.awt.image.BufferedImage;

import java.util.Random;

import javax.swing.*;

public class BounceApplet extends JApplet implements Runnable {

Ellipse2D.Double ball = new Ellipse2D.Double(25,75,30,30);

BufferedImage image;

Random seed = new Random();

Thread thread;

boolean bouncing = false;

int dx = 4;

int dy = 4;

final int DELAY = 50;

public void start() {

if(!bouncing) {

bouncing = true;

thread = new Thread(this);

thread.setPriority(Thread.NORM_PRIORITY);

thread.start();

}

}

public void stop() {

bouncing = false;

if(thread != null)

thread.interrupt();

thread = null;

}

public void paint(Graphics g) {

if(image == null)

initImage();

g.drawImage(image, 0, 0, this);

}

private void initImage() {

int w = getWidth();

int h = getHeight();

int type = BufferedImage.TYPE_INT_RGB;

image = new BufferedImage(w, h, type);

updateImage();

}

private void updateImage() {

Graphics2D g2 = (Graphics2D)image.getGraphics();

g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,

RenderingHints.VALUE_ANTIALIAS_ON);

g2.setBackground(getBackground());

g2.clearRect(0,0,image.getWidth(),image.getHeight());

g2.setPaint(Color.red);

g2.fill(ball);

g2.dispose();

}

public void run() {

while(image == null) {

try {

Thread.sleep(50);

} catch(InterruptedException e) {

stop();

}

}

while(bouncing) {

try {

Thread.sleep(DELAY);

} catch(InterruptedException e) {

stop();

}

advance();

}

}

private void advance() {

checkBoundries();

double x = ball.x + dx;

double y = ball.y + dy;

ball.setFrameFromDiagonal(x, y, x+ball.width, y+ball.height);

updateImage();

repaint();

}

private void checkBoundries() {

boolean changed = false;

if(ball.x + dx < 0 || ball.x + ball.width + dx > getWidth()) {

dx *= -1;

changed = true;

}

if(ball.y + dy < 0 || ball.y + ball.height + dy > getHeight()) {

dy *= -1;

changed = true;

}

if(changed)

adjustValues();

}

private void adjustValues() {

int value = 1 + seed.nextInt(5);

int opposite = 5 - value;

dx = ((dx > 0) ? 1 : -1)*value;

dy = ((dy > 0) ? 1 : -1)*opposite;

}

}

crwooda at 2007-7-12 9:26:54 > top of Java-index,Security,Cryptography...