在手机游戏的开发中常常会根据一条抛物线来模拟炮弹的轨迹。在已知炮弹的发射点,射程和射击高度的情况下,完全可由抛物线方程来模拟出炮弹的运行轨迹,当然,这里的模拟只是理想状态下的,并没有把风力等因素考虑进去。
根据炮弹的发射点(x1,y1),射程(cs)和射击高度(h)可得出抛物线的三个点:
p1:(x1,y1)
p2:(x2,y2) x2=x1+cs/2, y2=y1+h
p3:(x3,y3) x3=x1+cs, y3=y1
根据这三个点可列出抛物线方程
ax1^2+bx1+c=y1
ax2^2+bx2+c=y2
ax3^2+bx3+c=y3
计算方程得到该抛物线的系数a、b、c,得到a、b、c后,即可根据a、b、c计算出抛物线每点的轨迹。下面的例子将说明如何绘制轨迹:
例子运行效果如下:



例子canvas中的代码
import java.io.IOException;
import javax.microedition.lcdui.Graphics;
import javax.microedition.lcdui.Image;
import javax.microedition.lcdui.game.GameCanvas;
import javax.microedition.lcdui.game.Sprite;
import javax.microedition.lcdui.game.TiledLayer;
public
class MyCanvas extends GameCanvas implements Runnable
 ...{
//小船的位置
int x,y;
//小船精灵
Sprite ship;
//地图
TiledLayer background;
//图片
Image ship_IMG, sea_IMG, bullet_IMG;
//炮弹
Bullets bullets;
public MyCanvas()

...{
super(true);
//初始化船的位置
x =
10;
y =
60;
try

...{
ship_IMG = Image.createImage("/ship.png");
sea_IMG = Image.createImage("/sea.png");
bullet_IMG = Image.createImage("/bullet.png");
}
catch (IOException e)

...{
e.printStackTrace();
}
//初始化炮弹
bullets =
new Bullets(bullet_IMG);
//初始化小船
ship =
new Sprite(ship_IMG, 24, 30);
ship.setPosition(x, y);
//初始化地图
background =
new TiledLayer(20, 6, sea_IMG, 32, 32);
background.createAnimatedTile(1);
int[][] map =
new
int[][]

...{

...{ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 },

...{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },

...{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },

...{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },

...{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },

...{ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6 }
};
//绘制地图
for(int i =
0 ; i < map.length ; i ++)

...{
for(int j =
0 ; j < map[i].length ; j++)

...{
background.setCell(j, i, map[i][j]);
}
}
Thread th =
new Thread(this);
th.start();
}
private
int k =
0;
public
void run()

...{
Graphics g = getGraphics();
while(true)

...{
//显示出水的流动
k++;
if(k==10)

...{
if(background.getAnimatedTile(-1) ==
1)

...{
background.setAnimatedTile(-1, 2);
}
else
if(background.getAnimatedTile(-1) ==
2)

...{
background.setAnimatedTile(-1, 1);
}
k =
0;
}
//主控制
support(g);
//绘制
draw(g);
try

...{
Thread.sleep(35);
}
catch (InterruptedException e)

...{
e.printStackTrace();
}
}
}
public
void support(Graphics g)

...{
//控制船的移动及发射
int keyCode = getKeyStates();
switch(keyCode)

...{
case UP_PRESSED:
y = Math.max(0, y -
2);
if(ship.getFrame() >=
2)
ship.setFrame(0);
else
ship.nextFrame();
break;
case DOWN_PRESSED:
y = Math.min(getHeight(), y +
2);
if(ship.getFrame() <=
2
|| ship.getFrame() >=
5)
ship.setFrame(3);
else
ship.nextFrame();
break;
case LEFT_PRESSED:
x = Math.max(0, x -
2);
if(ship.getFrame() <=
5
|| ship.getFrame() >=
8)
ship.setFrame(6);
else
ship.nextFrame();
break;
case RIGHT_PRESSED:
x = Math.min(getWidth(), x +
2);
if(ship.getFrame() <=
8
|| ship.getFrame() >=
11)
ship.setFrame(9);
else
ship.nextFrame();
break;
case FIRE_PRESSED:
if(!bullets.isfire)

...{
bullets.isfire =
true;
bullets.setPoint(x+13,y);
}
break;
}
ship.setPosition(this.x, this.y);
}

/**//**
* 绘制
* @param g
*/
public
void draw(Graphics g)

...{
g.setColor(0xffffff);
g.fillRect(0,0,this.getWidth(),this.getHeight());
g.setColor(0x000000);
background.paint(g);
bullets.drawBullets(g);
ship.paint(g);
flushGraphics();
}
}
 /**//**
* 炮弹
* <p>Title: Bullets</p>
* <p>Description: </p>
* <p>Copyright: Copyright (c) 2005</p>
* <p>Date: 2006-3-2</p>
* @author ZGY
* @version 1.0
*/
class Bullets extends Sprite
 ...{
boolean isfire =
false;
//炮弹的发射点
int bulletX, bulletY;
//炮弹的射程
int shotWidth =
50;
//炮弹的射程高度
int shotHeight = shotWidth/2-10;
//炮弹的速度
int shotSpeed =
3;
//炮弹抛物线的系数
double a,b,c;
public Bullets(Image image)

...{
super(image, 15, 15);
}

/**//**
* 初始化炮弹
* @param x
* @param y
*/
public
void setPoint(int x, int y)

...{
//初始化炮弹的发射点
this.bulletX = x;
this.bulletY = y;
//根据炮弹的发射点、高度、射程计算出炮弹抛物线的三点
int x1 = bulletX;
int y1 = bulletY;
int x2 = bulletX+shotWidth/2;
int y2 = bulletY-shotHeight;
int x3 = bulletX+shotWidth;
int y3 = bulletY;
//根据抛物线方程ax^2+bx+c=y,得方程组
//ax1^2+bx1+c=y1
//ax2^2+bx2+c=y2
//ax3^2+bx3+c=y3
//解方程组得抛物线的a,b,c
b = ((y1-y3)*(x1*x1-x2*x2)-(y1-y2)*(x1*x1-x3*x3))/((x1-x3)*(x1*x1-x2*x2)-(x1-x2)*(x1*x1-x3*x3));
a = ((y1-y2)-b*(x1-x2))/(x1*x1-x2*x2);
c = y1-a*x1*x1-b*x1;
}

/**//**
* 绘出炮弹
* @param g
*/
public
void drawBullets(Graphics g)

...{
if(isfire)

...{
int k = (int)(a*bulletX*bulletX+b*bulletX+c);
setPosition(bulletX, k);
paint(g);
//炮弹的速度
bulletX += shotSpeed;
//炮弹将消失于小船的水平线
if(k > bulletY)

...{
nextFrame();
if(getFrame() ==
2)

...{
isfire =
false;
setFrame(0);
}
}
}
}
}
1
|