Game character movement

Hi,

I've got a system were I have constants for each of the compose points, and using a switch on that direction:

For example, if north - speed from y, is east + x, and so on.

This seems to work well, but I've always wanted to use degrees for the direction, rather then constants.

I've made a little image to show what I'm after, for some reason my browser was being redirected when trying to view it, so I've made a little html to display it and can be found here: http://acquiesce.awardspace.co.uk/temp/viewImg.html

In actual fact, the example i have there would be the equivalent of north-east in my current system.

I've also put what I've done so far, http://acquiesce.awardspace.co.uk/temp/MovementTester.java, the sheep.png is on the viewImg, just save as target.

I had this idea of having an up vector (Line2D), this vector could then be rotated by the characters direction to get a new line, then, say speed was 10, 10 units up this line would be the new position for the character.

Does that make sense to people?

I guess the only thing left to do is get the new pos that's 10 (or whatever speed is) units up the direction line, but I have no idea, how to do this.

Can anyone add any thoughts? I remember doing something like this before, so I'll see what I can think of.

Thanks,

Luke

[1381 byte] By [dfgstga] at [2007-11-15]
# 1

Just thought, what I need to to get a sub-line, that is a, say, 10 units in length.

Just thinking, doesn't help much tho :?

dfgstga at 2007-7-29 > top of java,Security,Cryptography...
# 2

after doing a bit of research on the topic, i've updated the image now, it's turning into a bit of a math issue rather then a java thing, sorry about that :(

I'll try some of the maths boffs, and shall post what i find out here :)

dfgstga at 2007-7-29 > top of java,Security,Cryptography...
# 3

I do make my life needlessly complicated at times.

All i needed to do was change the length of the up line, so what was all this talk about circles and points on a circumference? I don't know... Anyway, here;s what I've ended up with, the sprite (sheep) follows the mouse around when moved:

import java.io.File;

import java.awt.*;

import java.awt.event.*;

import java.awt.image.*;

import java.awt.geom.*;

import javax.swing.JFrame;

import javax.imageio.*;

public class MovementTester extends JFrame implements

MouseMotionListener,MouseWheelListener

{

public static void main(String[] args) {new MovementTester();}

// The point were the sheep is to be drawn

private Point2D pos=null;

// The sheep direction (in degrees)

private double dir=45;

// The speed the sheep is to move

private double speed=10;

// Face the direction

private boolean faceDir=true;

// The centre of the sheep

private Point2D sheepCentre=null;

// The sheep

private BufferedImage sheep=null;

// The up vector

private Point2D up=null;

// The centre of the frame

private Point2D centre=null;

public MovementTester()

{

this.setSize(800,600);

// Setup the sheep

setupSheep();

// Set the centre

centre=new Point2D.Double(this.getWidth()/2,this.getHeight()/2);

// Add the mouse thingys

this.addMouseMotionListener(this);

this.addMouseWheelListener(this);

this.setDefaultCloseOperation(EXIT_ON_CLOSE);

this.setVisible(true);

}

private void setupSheep()

{

try {

sheep=ImageIO.read(new File("tester\\Images\\sheep.png"));

} catch (Exception ex) {ex.printStackTrace();}

// Draw in the middle

double x=(this.getWidth()/2)-(sheep.getWidth()/2);

double y=(this.getHeight()/2)-(sheep.getHeight()/2);

pos=new Point2D.Double(x,y);

}

public void paint(Graphics g)

{

//super.paint(g);

// The buffer

BufferedImage buff=new BufferedImage(this.getWidth(),this.getHeight(),

BufferedImage.TYPE_4BYTE_ABGR_PRE);

// Get the buff g

Graphics2D buffG=(Graphics2D)buff.getGraphics();

if (isOpaque()) { //paint background

buffG.setColor(getBackground());

buffG.fillRect(0, 0, getWidth(), getHeight());

}

// The up vector (sheep x and y - speed)

up=new Point2D.Double(pos.getX(),pos.getY()-speed);

// The up line from sheep to up

Line2D upLine=new Line2D.Double(pos,up);

// The direction line

Line2D dirLine=null;

// Draw the up line in blue

buffG.setPaint(Color.blue);

buffG.draw(upLine);

// Roate the up line

AffineTransform alf=AffineTransform.getRotateInstance(

Math.toRadians(dir),upLine.getX1(),upLine.getY1()

);

// Get the transformed shaoe as a line

dirLine=toLine(alf.createTransformedShape(upLine));

// Draw the direction line in red

buffG.setPaint(Color.red);

buffG.draw(dirLine);

// Move to end of the dir line

pos=new Point2D.Double(dirLine.getX2(),dirLine.getY2());

// The centre of the sheep

sheepCentre=new Point2D.Double(pos.getX()+(sheep.getWidth()/2),

pos.getY()+(sheep.getHeight()/2));

// If face dir

if (faceDir)

{

// Rotate to dir

//sheep=rotate(sheep,dir,pos.getX(),pos.getY(),null);

}

// Draw the sheep

buffG.drawImage(sheep,(int)pos.getX(),(int)pos.getY(),null);

// Draw the buff

g.drawImage(buff,0,0,null);

}

public void mouseMoved(MouseEvent e)

{

// Get the mouse x,y

double mX=e.getPoint().getX();

double mY=e.getPoint().getY();

// Make a point at the top middle of the frame

Point2D top=new Point2D.Double(centre.getX(),0);

// The dist of top to centre (side a)

double sideA=Point.distance(top.getX(),top.getY(),

centre.getX(),centre.getY());

// The dist pf centre to mouse point (side b)

double sideB=Point.distance(centre.getX(),centre.getY(),

mX,mY);

// Between mouse and top (side c)

double sideC=Point.distance(mX,mY,top.getX(),top.getY());

// We wanna find the angle abound the centre

// So the cos of angleCen

double cosCen=((sideA*sideA)+(sideB*sideB)-(sideC*sideC))/(

2*(sideA*sideB));

// Arc cos to get angle

dir=Math.toDegrees(Math.acos(cosCen));

// If mouse is on left side of centre

if (mX<centre.getX())

{

// - from 360 to get the reverse angle

dir=360-dir;

}

// Repaint

repaint();

}

public void mouseDragged(MouseEvent e) {}

public void mouseWheelMoved(MouseWheelEvent e)

{

// If up (away)

if (e.getWheelRotation()><0)

{

// More speed

speed=speed+4;

}

else {speed=speed-4;}

}

public static BufferedImage rotate(BufferedImage in,double angle,

double x,double y,RenderingHints rh)

{

//

AffineTransform aff = AffineTransform.getRotateInstance(angle,x,y);

// The transform op

AffineTransformOp op = new AffineTransformOp(aff,rh);

// Return the rotated bufferedImage

return op.filter(in,null);

}

public static Line2D toLine(Shape s)

{

return toLine(s.getPathIterator(null));

}

public static Line2D toLine(PathIterator path)

{

// The line

Line2D line=null;

// The start of the line

Point2D start=null;

// The end of the line

Point2D end=null;

// Two points (x1,y1,x2,y2)

double[] points=new double[2];

// Get the first segment, should be move to and the stat of the line

path.currentSegment(points);

// Make the start point

start=new Point2D.Double(points[0],points[1]);

// Move to the next segment

path.next();

// Get the next segment, line to and the end point

path.currentSegment(points);

// Make the end point

end=new Point2D.Double(points[0],points[1]);

// Make the line

line=new Line2D.Double(start,end);

// Return the line

return line;

}

}

I thought it would be cool if the image rotated to face the direction it's moving in, but when I tried that using the AffineTransformOp I got a RasterFormatException.

I've had problems with op's and image loaded using the ImageIO.read() before, but they work fine loaded from the JPEGDecoder ?

Guess I'll have to make a PNGDecoder next :|

Anyway, I'm happy for the time being watching my sheep dance about. :D

Luke

dfgstga at 2007-7-29 > top of java,Security,Cryptography...
# 4

import java.awt.*;

import java.awt.event.*;

import java.awt.image.*;

import java.awt.geom.*;

import java.io.File;

import javax.imageio.*;

import javax.swing.JFrame;

public class MT extends JFrame implements MouseMotionListener,MouseWheelListener

{

public static void main(String[] args) {new MT();}

// The point were the sheep is to be drawn

private Point2D pos=null;

// The sheep direction (in degrees)

private double dir=45;

// The speed the sheep is to move

private double speed=10;

// Face the direction

private boolean faceDir=true;

// The centre of the sheep

private Point2D sheepCentre=null;

// The sheep

private BufferedImage sheep=null;

// The up vector

private Point2D up=null;

// The centre of the frame

private Point2D centre=null;

BufferedImage buff;

public MT()

{

this.setSize(800,600);

// Setup the sheep

setupSheep();

// Set the centre

centre=new Point2D.Double(this.getWidth()/2,this.getHeight()/2);

// Add the mouse thingys

this.addMouseMotionListener(this);

this.addMouseWheelListener(this);

this.setDefaultCloseOperation(EXIT_ON_CLOSE);

this.setVisible(true);

}

private void setupSheep()

{

try {

sheep=ImageIO.read(new File("sheep.png"));

} catch (Exception ex) {ex.printStackTrace();}

// Draw in the middle

double x=(this.getWidth()/2)-(sheep.getWidth()/2);

double y=(this.getHeight()/2)-(sheep.getHeight()/2);

pos=new Point2D.Double(x,y);

}

public void paint(Graphics g)

{

if(buff == null)

buff=new BufferedImage(this.getWidth(),this.getHeight(),

BufferedImage.TYPE_4BYTE_ABGR_PRE);

// Draw the buff

g.drawImage(buff,0,0,null);

}

private void updateBuffer()

{

// Get the buff g

Graphics2D buffG=buff.createGraphics();

buffG.setColor(getBackground());

buffG.fillRect(0, 0, getWidth(), getHeight());

// The up vector (sheep x and y - speed)

up=new Point2D.Double(pos.getX(),pos.getY()-speed);

// The up line from sheep to up

Line2D upLine=new Line2D.Double(pos,up);

// The direction line

Line2D dirLine=null;

// Draw the up line in blue

buffG.setPaint(Color.blue);

buffG.draw(upLine);

// Roate the up line

AffineTransform alf=AffineTransform.getRotateInstance(

Math.toRadians(dir),upLine.getX1(),upLine.getY1()

);

// Get the transformed shaoe as a line

dirLine=toLine(alf.createTransformedShape(upLine));

// Draw the direction line in red

buffG.setPaint(Color.red);

buffG.draw(dirLine);

// Move to end of the dir line

pos=new Point2D.Double(dirLine.getX2(),dirLine.getY2());

// The centre of the sheep

sheepCentre=new Point2D.Double(pos.getX()+(sheep.getWidth()/2),

pos.getY()+(sheep.getHeight()/2));

// If face dir

if (faceDir)

{

AffineTransform at = getTransform(sheep,dir,pos.getX(),pos.getY());

buffG.drawRenderedImage(sheep, at);

} else {

// Draw the sheep

buffG.drawImage(sheep,(int)pos.getX(),(int)pos.getY(),null);

}

buffG.dispose();

}

public void mouseMoved(MouseEvent e)

{

if(buff == null) return;

// Get the mouse x,y

double mX=e.getPoint().getX();

double mY=e.getPoint().getY();

// Make a point at the top middle of the frame

Point2D top=new Point2D.Double(centre.getX(),0);

// The dist of top to centre (side a)

double sideA=Point.distance(top.getX(),top.getY(),

centre.getX(),centre.getY());

// The dist pf centre to mouse point (side b)

double sideB=Point.distance(centre.getX(),centre.getY(),

mX,mY);

// Between mouse and top (side c)

double sideC=Point.distance(mX,mY,top.getX(),top.getY());

// We wanna find the angle abound the centre

// So the cos of angleCen

double cosCen=((sideA*sideA)+(sideB*sideB)-(sideC*sideC))/(

2*(sideA*sideB));

// Arc cos to get angle

dir=Math.toDegrees(Math.acos(cosCen));

// If mouse is on left side of centre

if (mX<centre.getX())

{

// - from 360 to get the reverse angle

dir=360-dir;

}

// Repaint

updateBuffer();

repaint();

}

public void mouseDragged(MouseEvent e) {}

public void mouseWheelMoved(MouseWheelEvent e)

{

// If up (away)

if (e.getWheelRotation() > 0)

{

// More speed

speed=speed+4;

}

else {speed=speed-4;}

}

public AffineTransform getTransform(BufferedImage in,double angle,

double x,double y)

{

double theta = Math.toRadians(angle) - Math.PI/2;

double cos = Math.abs(Math.cos(theta));

double sin = Math.abs(Math.sin(theta));

int iw = in.getWidth();

int ih = in.getHeight();

double w = iw*cos + ih*sin;

double h = ih*cos + iw*sin;

double ix = x + (w - iw)/2;

double iy = y + (h - ih)/2;

AffineTransform aff = AffineTransform.getTranslateInstance(ix, iy);

aff.rotate(theta, iw/2, ih/2);

return aff;

}

public static Line2D toLine(Shape s)

{

return toLine(s.getPathIterator(null));

}

public static Line2D toLine(PathIterator path)

{

// The line

Line2D line=null;

// The start of the line

Point2D start=null;

// The end of the line

Point2D end=null;

// Two points (x1,y1,x2,y2)

double[] points=new double[2];

// Get the first segment, should be move to and the stat of the line

path.currentSegment(points);

// Make the start point

start=new Point2D.Double(points[0],points[1]);

// Move to the next segment

path.next();

// Get the next segment, line to and the end point

path.currentSegment(points);

// Make the end point

end=new Point2D.Double(points[0],points[1]);

// Make the line

line=new Line2D.Double(start,end);

// Return the line

return line;

}

}

crwooda at 2007-7-29 > top of java,Security,Cryptography...
# 5

Thanks,

I must say, that I didn't kno about the Graphics2D.drawRenderedImage() method, it looks really cool now.

I've stated applying the line movement thing into my Sprite class already, have to do the rotation thing now.

Looking back at my code, it was a real joy to delete all the line of code and replace them with this new much shorter method.

I have game idea a plenty now, I'll have to make a start on one :D

Thanks a lot,

Luke

dfgstga at 2007-7-29 > top of java,Security,Cryptography...