Samstag, 16. Juni 2007

Defining waypoints for your sprite, or, moving your sprite on a straight line

If you want to move your sprite from one point to another on a straight line, you will have to calculate the line based on the two positions given. Since the equation for a line is

mx+b = y

you will have to calculate the slope (m) and the intercept (b) to be able to calculate any position in between the starting and the end position. The two methods for doing this in J2ME:




class Util {
/**
* Slope calculation for line given by two x-y-positions
*
* @param x1 First position's x-parameter
* @param y1 First position's y-parameter
* @param x2 Second position's x-parameter
* @param y2 Second position's y-parameter
* @return calculated slope value
*/
public static double calcLineSlope(int x1, int y1, int x2, int y2) {
double dx = x1 - x2;
double dy = y1 - y2;
if ((dx != 0) && (dy != 0)) {
return (dy / dx);
} else {
return 0;
}
}

/**
* Intercept calculation for line given by x-y-position and slope
*
* @param x x-parameter of given position
* @param y y-parameter of given position
* @param m slope of line
* @return calculated intercept value
*/
public static double calcLineIntercept(int x, int y, double m) {
if (m != 0) {
return y - m*x;
} else {
return 0;
}
}
}


 


To put these functions into use, you can try something like the following EnemySprite class



import javax.microedition.lcdui.Image;
import javax.microedition.lcdui.game.Sprite;

class EnemySprite extends Sprite {

double cur_m;
double cur_b;
int target_x;
int target_y;

int speed;

// Constructor, is called when you instantiate your EnemySprite
public EnemySprite(Image img) {
super(img);

speed = 5;

// Starting position (20, 20), target position (30, 100)
this.setPosition(20, 20);
target_x = 30; target_y = 100;
cur_m = Util.calcLineSlope(target_x, target_y, this.getX(), this.getY());
cur_b = Util.calcLineIntercept(this.getX(), this.getY(), cur_m);
}

// Call this method in your game loop
public void update () {
if ((this.getX() != target_x) || (this.getY() != target_y)) {
double dx = Math.abs(target_x - this.getX());
double dy = Math.abs(target_y - this.getY());
if ((dx != 0) && (dy != 0)) {
int nextx = 0;

if (Math.abs(this.getX() - target_x) < speed) {
nextx = target_x;
} else {
nextx = (this.getX() < target_x) ?
this.getX() + speed :
this.getX() - speed;
}
int nexty = (int)(nextx * cur_m + cur_b);

this.setPosition(nextx, nexty);
} else {
if (dx != 0) {
if (Math.abs(this.getX() - target_x) < 2*speed) {
this.setPosition(target_x, this.getY());
} else {
int nextx = (this.getX() < target_x) ?
this.getX() + 2*speed :
this.getX() - 2*speed;
this.setPosition(nextx, this.getY());
}
}
if (dy != 0) {
if (Math.abs(this.getY() - target_y) < 2*speed) {
this.setPosition(this.getX(), target_y);
} else {
int nexty = (this.getY() < target_y) ?
this.getY() + 2*speed:
this.getY() - 2*speed;
this.setPosition(this.getX(), nexty);
}
}
}
} else {

// Target position reached, inititalize next waypoint...

}
}
}


 


This will only work with MIDP 2.0, since floating-point-values are not supported in MIDP 1.0 to my knowledge.

To copy and paste this code, please open the source of this page and copy from there.



--thgc