在手机游戏的开发中常常会根据一条抛物线来模拟炮弹的轨迹。在已知炮弹的发射点,射程和射击高度的情况下,完全可由
抛物线方程来模拟出炮弹的运行轨迹,当然,这里的模拟只是理想状态下的,并没有把风力等因素考虑进去。
根据炮弹的发射点(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计算出抛物线每点的轨迹。
下面的例子将说明如何绘制轨迹:
例子源码及图片下载
我的msn是zhagy_1981@hotmail.com,欢迎指出不足之处。
例子运行效果如下:
例子canvas中的代码
{geshibot lang="javascript"}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.length ; j++)
{
background.setCell(j, i, map[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);
}
}
}
}
}{/geshibot}