【发布时间】:2011-06-13 22:59:46
【问题描述】:
想知道是否有人能指出我正确的方向。
我希望能够将一个对象(如子弹)从静态位置移动到屏幕上的任何区域。
我对简单的水平和垂直运动没有任何问题。 IE。 x +/- 1 或 y +/- 1。 但是当涉及到像子弹这样的物体可以在任何程度上移动/动画时,我不太确定如何通过使动画看起来平滑来做到这一点。例如,在 18、45 或 33 度角时,像 y+1、x+1、y+1 之类的算法......不会使动画非常流畅。
提前致谢
P.s 也许已经有一些文档了?
更新
感谢所有回复的人。
这是我目前根据您的 cmets 编写的代码。
package com.bullet;
//imports go here
public class canvas extends SurfaceView implements OnTouchListener, SurfaceHolder.Callback{
private Bitmap bullet;
private int bulletStartX, bulletStartY;
private int bulletX, bulletY;
private int bulletEndX = -1;
private int bulletEndY = -1;
private int incX = 0;
private int incY = 0;
private SurfaceHolder holder;
private Thread t;
public canvas(Context context) {
super(context);
this.setBackgroundColor(Color.WHITE);
setFocusable(true);
setFocusableInTouchMode(true);
setOnTouchListener(this);
bulletStartX = 0;
bulletStartY = 0;
bulletX = bulletStartX;
bulletY = bulletStartY;
bullet = BitmapFactory.decodeResource(getResources(), R.drawable.bullet);
holder = getHolder();
holder.addCallback(this);
}
public void onDraw(Canvas canvas){
if(bulletEndX != -1 && bulletEndY != -1){
Log.e("here", "drawing bullet");
Log.e("here", "x: " + bulletX + ", y: " + bulletY);
canvas.drawBitmap(bullet, bulletX, bulletY, null);
}
}
public void updateBullet(){
Log.e("here", "inc bullet");
bulletX += incX;
bulletY += incY;
if(bulletX > bulletEndX){
bulletEndX = -1;
}
if(bulletY > bulletEndY){
bulletEndY = -1;
}
}
@Override
public boolean onTouch(View v, MotionEvent event) {
int[] coordinates = {(int) event.getX(), (int) event.getY()};
int motion = event.getAction();
switch(motion){
case MotionEvent.ACTION_DOWN:
break;
case MotionEvent.ACTION_MOVE:
break;
case MotionEvent.ACTION_UP:
bulletX = bulletStartX;
bulletY = bulletStartY;
bulletEndX = (int) event.getX();
bulletEndY = (int) event.getY();
incX = (int) bulletEndX / 50;
incY = (int) bulletEndY / 50;
Log.e("here", "touch up");
break;
}
return true;
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
// TODO Auto-generated method stub
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
t = new GameThread(this, holder);
t.start();
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
// TODO Auto-generated method stub
}
//Thread class
class GameThread extends Thread{
private canvas canvas;
private SurfaceHolder holder;
private boolean run = false;
long delay = 70;
public GameThread(canvas canvas, SurfaceHolder holder){
this.holder = holder;
this.canvas = canvas;
startThread(true);
}
public boolean isRunning(){
return this.run;
}
private void startThread(boolean run){
this.run = run;
}
public void stopThread(){
this.run = false;
}
@Override
public void run(){
while(run){
Canvas c = null;
try {
//lock canvas so nothing else can use it
c = holder.lockCanvas(null);
synchronized (holder) {
//clear the screen with the black painter.
//This is where we draw the game engine.
//Log.e("drawthread", "running");
if(bulletEndX != -1 && bulletEndY != -1){
updateBullet();
canvas.postInvalidate();
}
canvas.onDraw(c);
//Log.e("drawthread", "ran");
try {
sleep(32);
//Log.e("slept", "sleeping");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
} finally {
// do this in a finally so that if an exception is thrown
// during the above, we don't leave the Surface in an
// inconsistent state
if (c != null) {
holder.unlockCanvasAndPost(c);
}
}
}
}
}
}
绘图效果很好,但是有两个问题。
1. 绘图相当缓慢和跳跃……与类似这个 java 示例 http://www.youtube.com/watch?v=-g5CyPQlIo4
相比2. 如果点击是在接近 Y = 0 的位置,那么由于 ENDY / FRAME 的值小于 1,意味着向上舍入到 0 并且子弹穿过屏幕顶部,而不是 Y 的偶尔增量。
@SyntaxT3rr0r 你的权利,这可能是最好的方法。但是你知道有什么文件可以实现这样的东西吗?
再次感谢所有回复的人
【问题讨论】:
-
屏幕坐标!=世界坐标。游戏通常使用任意坐标系,然后将您的对象转换为屏幕坐标以适应您的屏幕(例如您可以在线玩 星际争霸 2 与对手,例如, 1280x960 或 1600x1200 并且它不应为你的对手改变一个 yota:因为你仍然在同一个任意游戏坐标系统中玩)。在比屏幕坐标更大的坐标系中计算子弹的位置。这只是开始,它不是答案,因此是评论。
标签: java android canvas 2d bulletphysics