PDA

Click to See Complete Forum and Search --> : Java "Crab" Applet


robcyb
Feb 14th, 2006, 09:11 AM
Hey all,

Am new here :wave:. Nice to see fellow developers helping one another.

I have recently began to delve into looking at Java Applets and animation of objects within applets. As a mini-project I have embarked on creating a "crab" Applet that simulates some sort of crab behaviour.

Each instance of a "crab" is to move around randomly on the screen (within the limits of the applet window) and when a collision is detected the coordinates are inverted to creat a "bounce" effect. However, the work I have done so far is very simple and does not necessarily do much to what I would like to achieve from this little adventure :rolleyes:.

The source code so far is...

import java.awt.*;
import java.applet.*;

class CollideCrab
{
int width, height;
public static final int diameter=20;
double x, y, xinc, yinc, coll_x, coll_y;
boolean collide;
Color color;
Graphics g;

public CollideCrab(int w, int h, int x, int y, double xinc, double yinc, Color c)
{
width=w;
height=h;
this.x=x;
this.y=y;
this.xinc=xinc;
this.yinc=yinc;
color=c;
}

public double getCenterX() {return x+diameter/2;}
public double getCenterY() {return y+diameter/2;}

public void move()
{
if (collide)
{
double xvect=coll_x-getCenterX();
double yvect=coll_y-getCenterY();

if((xinc>0 && xvect>0) || (xinc<0 && xvect<0))
xinc=-xinc;

if((yinc>0 && yvect>0) || (yinc<0 && yvect<0))
yinc=-yinc;

collide=false;
}

x+=xinc;
y+=yinc;

if(x<0 || x>width-diameter)
{
xinc=-xinc;
x+=xinc;
}

if(y<0 || y>height-diameter)
{
yinc=-yinc;
y+=yinc;
}
}

public void hit(CollideCrab b)
{
if(!collide)
{
coll_x=b.getCenterX();
coll_y=b.getCenterY();
collide=true;
}
}

public void paint(Graphics gr)
{
g=gr;
g.setColor(color);
g.fillOval((int)x,(int)y,diameter,diameter);
}
}

public class fiddlerCrabs extends Applet implements Runnable
{
Thread runner;
Image Buffer;
Graphics gBuffer;
CollideCrab crab[];

static final int MAX=5;

public void init()
{
Buffer=createImage(size().width,size().height);
gBuffer=Buffer.getGraphics();

crab=new CollideCrab[MAX];

int w=size().width;
int h=size().height;

crab[0]=new CollideCrab(w,h,50,20,1.5,2.0,Color.orange);
crab[1]=new CollideCrab(w,h,60,100,2.0,-3.0,Color.red);
crab[2]=new CollideCrab(w,h,15,70,-2.0,-2.5,Color.pink);
crab[3]=new CollideCrab(w,h,150,60,-2.7,-2.0,Color.cyan);
crab[4]=new CollideCrab(w,h,210,30,2.2,-3.5,Color.magenta);
}

public void start()
{
if (runner == null)
{
runner = new Thread (this);
runner.start();
}
}

public void stop()
{
if (runner != null)
{
runner.stop();
runner = null;
}
}

public void run()
{
while(true)
{
try {Thread.currentThread().sleep(30);}
catch (Exception e) { }

for(int i=0;i<MAX;i++)
crab[i].move();

handleCollision();

repaint();
}
}

boolean collide(CollideCrab b1, CollideCrab b2)
{
double wx=b1.getCenterX()-b2.getCenterX();
double wy=b1.getCenterY()-b2.getCenterY();

double distance=Math.sqrt(wx*wx+wy*wy);

if(distance<b1.diameter)
{
return true;
}

return false;
}


private void handleCollision()
{
for(int i=0;i<MAX;i++)
for(int j=0;j<MAX;j++)
{
if(i!=j)
{
if(collide(crab[i], crab[j]))
{
crab[i].hit(crab[j]);
crab[j].hit(crab[i]);
}
}
}
}

public void update(Graphics g)
{
paint(g);
}

public void paint(Graphics g)
{
gBuffer.setColor(Color.blue);
gBuffer.fillRect(0,0,size().width,size().height);

for(int i=0;i<MAX;i++)
crab[i].paint(gBuffer);

g.drawImage (Buffer,0,0, this);
}
}

As you can see from the code, it's very simple. I would like help on the following issues though :).

I would like the crabs to each have a label above them (crabx) to keep a track of what each crab is.

A for loop for creating an instance of each crab with the random startx and starty variables to move a crab across the scene. (so that more crabs can be added dynamically and not have to hard code each crab).

If anyone could help, it would be most appreciated!

System_Error
Feb 14th, 2006, 08:01 PM
First Problem:

g.drawString(String, x, y);


Second:

Create two random objects (possibly just one) and an array of crab objects:



Crab[] c = new Crab[5];
for (int index=0; index<c.length; ++c)
{
c = new Crab(randomx.nextInt(), randomy.nextInt());
}


That's not everything, but it should get you started.

robcyb
Feb 15th, 2006, 06:00 AM
Thanks for the help and advice!

Have now done the modficications and a major code cleanup/variable naming changes.

However, the problem I have now is with the starting position of each crab (they all seem to start at the same point??). It's probably my poor lack of math logic.

New Code.....

// fiddlerCrabs.java
// Robert Simmons 13th Feburary 2006.
// Last Change: 15th February 2006 @ 11:56.

import java.applet.*;
import javax.swing.*;
import java.util.*;
import java.awt.*;
import java.awt.Graphics.*;

public class fiddlerCrabs extends JApplet implements Runnable
{
Thread tThread;
Image tImageBuffer;
Graphics tGraphicsBuffer;
Crab tCrab[];

// Number of crabs to be drawn to scence.
static final int tNoOfCrabs = 10;

public void init()
{
tImageBuffer = createImage(size().width,size().height);
tGraphicsBuffer = tImageBuffer.getGraphics();

tCrab = new Crab[tNoOfCrabs];

int tWidth = size().width;
int tHeight = size().height;

for (int i=0; i < tCrab.length; i++)
{
String tCrabLabel = ("Crab" + (i+1));

int tPositionX = ((int)Math.random() + (50)*2);
int tPositionY = ((int)Math.random() *3 + 20);
double tIncrementX = (double)Math.random() + 1.5;
double tIncrementY = (double)Math.random() + 2.0;

// Create new instance of crab, passing: width, height, position on X Axis, position on Y Axis, Increment on X Axis, Increment on Y Axis, Colour and Text Label.
tCrab[i] = new Crab(tWidth, tHeight, tPositionX, tPositionY, tIncrementX, tIncrementY, Color.black, tCrabLabel);
}
}

public void start()
{
if (tThread == null)
{
tThread = new Thread (this);
tThread.start();
}
}

public void stop()
{
if (tThread != null)
{
tThread.stop();
tThread = null;
}
}

public void run()
{
while(true)
{
try
{
Thread.currentThread().sleep(30);
}

catch (Exception e)
{
// Do Nothing.
}

for(int i=0;i<tNoOfCrabs;i++)
{
tCrab[i].move();
}

handleCollision();

repaint();
}
}

boolean collide(Crab pCrab1, Crab pCrab2)
{
double wx = pCrab1.getCenterX() - pCrab2.getCenterX();
double wy = pCrab1.getCenterY() - pCrab2.getCenterY();

double distance = Math.sqrt(wx*wx+wy*wy);

if(distance < pCrab1.tCrabDiameter)
{
return true;
}

return false;
}


private void handleCollision()
{
for(int i=0; i < tNoOfCrabs; i++)
for(int j=0; j < tNoOfCrabs; j++)
{
if(i!=j)
{
if(collide(tCrab[i], tCrab[j]))
{
tCrab[i].hit(tCrab[j]);
tCrab[j].hit(tCrab[i]);
}
}
}
}

public void update(Graphics g)
{
paint(g);
}

public void paint(Graphics g)
{
tGraphicsBuffer.setColor(Color.gray);
tGraphicsBuffer.fillRect(0,0,size().width,size().height);

for(int i=0;i<tNoOfCrabs;i++)
{
tCrab[i].paint(tGraphicsBuffer);
}

g.drawImage (tImageBuffer,0,0, this);
}
}

And the class File....

// Crab.java
// Class File for constructing an instance of crab.
// Robert Simmons 13th Feburary 2006.
// Last Change: 15th February 2006 @ 11:56.

import java.awt.*;
import java.awt.Graphics.*;

class Crab
{
int tCrabWidth, tCrabHeight;

// Crab Circle Diameter.
public static final int tCrabDiameter = 15;

double tPositionX, tPositionY, tIncrementX, tIncrementY, tCollisionX, tCollisionY;
boolean tCollisionDetected;
String tCrabLabel;
Color tColour;

public Crab(int pCrabWidth, int pCrabHeight, int pCrabPositionX, int pCrabPositionY, double pIncrementX, double pIncrementY, Color pColour, String pString)
{
tCrabWidth = pCrabWidth;
tCrabHeight = pCrabHeight;
this.tPositionX = pCrabPositionX;
this.tPositionY = pCrabPositionY;
this.tIncrementX = pIncrementX;
this.tIncrementY = pIncrementY;
tColour = pColour;
tCrabLabel = pString;
}

public double getCenterX()
{
return tPositionX + tCrabDiameter / 2;
}

public double getCenterY()
{
return tPositionY + tCrabDiameter / 2;
}

public void move()
{
if (tCollisionDetected)
{
double tVectorX = tCollisionX - getCenterX();
double tVectorY = tCollisionY - getCenterY();

if((tIncrementX > 0 && tVectorX > 0) || (tIncrementX < 0 && tVectorX < 0))
{
tIncrementX =- tIncrementX;
}

if((tIncrementY > 0 && tVectorY > 0) || (tIncrementY < 0 && tVectorY < 0))
{
tIncrementY =- tIncrementY;
}

tCollisionDetected = false;
}

tPositionX += tIncrementX;
tPositionY += tIncrementY;

if(tPositionX < 0 || tPositionX > tCrabWidth - tCrabDiameter)
{
tIncrementX =- tIncrementX;
tPositionX += tIncrementX;
}

if(tPositionY < 0 || tPositionY > tCrabHeight - tCrabDiameter)
{
tIncrementY =- tIncrementY;
tPositionY += tIncrementY;
}
}

public void hit(Crab pCrab)
{
if(!tCollisionDetected)
{
tCollisionX = pCrab.getCenterX();
tCollisionY = pCrab.getCenterY();
tCollisionDetected = true;
}
}

public void paint(Graphics pGraphics)
{
pGraphics.setColor(tColour);
pGraphics.fillOval((int)tPositionX,(int)tPositionY,tCrabDiameter,tCrabDiameter);
pGraphics.drawString(tCrabLabel,((int)tPositionX)-7,((int)tPositionY)-5);
}
}

If anyone could help, it would be greatly appreciated.

robcyb
Feb 15th, 2006, 09:29 AM
ok, have solved that problem now :afrog:.

robcyb
Feb 15th, 2006, 10:22 AM
Ok, once again I have stumbled across yet another problem.

I am trying to add a layout manager to add some simple GUI functionality. However whatever I setup, it's getting overriden by the painting of the background and the button is getting lost.

I have done the following:

Container tContent = getContentPane();

JButton tStart = new JButton("Start");
tContent.add(tStart, BorderLayout.NORTH);
setContentPane(tContent);
setLayout(new FlowLayout());

setVisible(true);

However, I want to be able to add the rest to the south of the borderlayout (the crabs being drawn).

How do I go about setting this up :S?