画一个英雄并移动它



绘制英雄并移动它的最佳方法是什么?我只需要最好的代码。在写这篇文章之前,我找到了一种方法,但是当我使表面支架透明时,我意识到代码每隔一毫秒就会在旧的前面绘制新的位图。这条路对我来说有点慢,但是我错了。请帮帮我。实际上我有点困惑……

无论如何,这是我认为是滞后的代码:MainThread.java

/**
 * 
 */
package com.workspace.pockethero;

import android.graphics.Canvas;
import android.util.Log;
import android.view.SurfaceHolder;

/**
 * @author impaler
 *
 * The Main thread which contains the game loop. The thread must have access to 
 * the surface view and holder to trigger events every game tick.
 */
public class MainThread extends Thread {
    private static final String TAG = MainThread.class.getSimpleName();
    // Surface holder that can access the physical surface
    private SurfaceHolder surfaceHolder;
    // The actual view that handles inputs
    // and draws to the surface
    private MainGamePanel gamePanel;
    // flag to hold game state 
    private boolean running;
    public void setRunning(boolean running) {
        this.running = running;
    }
    public MainThread(SurfaceHolder surfaceHolder, MainGamePanel gamePanel) {
        super();
        this.surfaceHolder = surfaceHolder;
        this.gamePanel = gamePanel;
    }
    @Override
    public void run() {
        Canvas canvas;
        canvas = this.surfaceHolder.lockCanvas();
        Log.d(TAG, "Starting game loop");
        while (running) {
            canvas = null;
            // try locking the canvas for exclusive pixel editing
            // in the surface
            try {
                synchronized (surfaceHolder) {
                    // update game state
                    this.gamePanel.update();
                    // render state to the screen
                    // draws the canvas on the panel
                    this.gamePanel.render(canvas);
                }
            } finally {
                // in case of an exception the surface is not left in 
                // an inconsistent state
                if (canvas != null) {
                    surfaceHolder.unlockCanvasAndPost(canvas);
                }
            }   // end finally
        }
    }
}

MainGamePanel.java

/**
 * 
 */
package com.workspace.pockethero;
import com.workspace.pockethero.model.Droid;
import com.workspace.pockethero.buttons.*;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.util.Log;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;

/**
 * @author impaler
 * This is the main surface that handles the ontouch events and draws
 * the image to the screen.
 */
public class MainGamePanel extends SurfaceView implements
        SurfaceHolder.Callback {
    private static final String TAG = MainGamePanel.class.getSimpleName();
    private MainThread thread;
    public Droid droid;
    public Butt butt;
    public Butt1 butt1;
    public Butt2 butt2;
    public Butt3 butt3;
    public Buttz buttz;
    public Buttz1 buttz1;
    public Buttz2 buttz2;
    public Buttz3 buttz3;
    public Buttx buttx;
    public Build build;
    public int decentreX;
    public int decentreY;
    public int debottomA;
    public boolean moved;
    public boolean moved1;
    public boolean moved2;
    public boolean moved3;
    public boolean moved4;
    public boolean moved5;
    public boolean moved6;
    public boolean moved7;
    private Drawable myImage;
    public boolean mapPainted;
    public MainGamePanel(Context context) {
        super(context);
        // adding the callback (this) to the surface holder to intercept events
        getHolder().addCallback(this);
        // create droid and load bitmap
        decentreX = PocketHero.centreX;
        decentreY = PocketHero.centreY;
        debottomA = PocketHero.bottomA;

        droid = new Droid(BitmapFactory.decodeResource(getResources(), R.drawable.herod), decentreX, decentreY);
        butt = new Butt(BitmapFactory.decodeResource(getResources(), R.drawable.button), 110, debottomA - 70);
        butt1 = new Butt1(BitmapFactory.decodeResource(getResources(), R.drawable.button1), 70, debottomA - 110);
        butt2 = new Butt2(BitmapFactory.decodeResource(getResources(), R.drawable.button2), 30, debottomA - 70);
        butt3 = new Butt3(BitmapFactory.decodeResource(getResources(), R.drawable.button3), 70, debottomA - 30);
        buttz = new Buttz(BitmapFactory.decodeResource(getResources(), R.drawable.zbutton), 110, debottomA - 110);
        buttz1 = new Buttz1(BitmapFactory.decodeResource(getResources(), R.drawable.zbutton1), 30, debottomA - 110);
        buttz2 = new Buttz2(BitmapFactory.decodeResource(getResources(), R.drawable.zbutton2), 30, debottomA - 30);
        buttz3 = new Buttz3(BitmapFactory.decodeResource(getResources(), R.drawable.zbutton3), 110, debottomA - 30);
        buttx = new Buttx(BitmapFactory.decodeResource(getResources(), R.drawable.xbutton), 70, debottomA - 70);
        build = new Build(BitmapFactory.decodeResource(getResources(), R.drawable.building), 500, 200);
        // create the game loop thread
        //300 indicates start position of bitmapfield on screen

        thread = new MainThread(getHolder(), this);
        // make the GamePanel focusable so it can handle events
        setFocusable(true);
        this.setOnTouchListener(new OnTouchListener() {
            public boolean onTouch(View V, MotionEvent event) {
                if (event.getAction() == MotionEvent.ACTION_DOWN) {
                    // delegating event handling to the droid
                    handleActionDown((int)event.getX(), (int)event.getY());
                } if (event.getAction() == MotionEvent.ACTION_MOVE) {
                    handleActionDown((int)event.getX(), (int)event.getY());
                    // the gestures
                } if (event.getAction() == MotionEvent.ACTION_UP) {
                    // touch was released
                    if (droid.touched) {
                        droid.setTouched(false);
                    }
                    if (droid.touched1) {
                        droid.setTouched1(false);
                    }
                    if (droid.touched2) {
                        droid.setTouched2(false);
                    }
                    if (droid.touched3) {
                        droid.setTouched3(false);
                    }
                }
                return true;
            }
        });
    }
    public void surfaceChanged(SurfaceHolder holder, int format, int width,
            int height) {
    }

    public void surfaceCreated(SurfaceHolder holder) {
        // at this point the surface is created and
        // we can safely start the game loop
        thread.setRunning(true);
        thread.start();
    }

    public void surfaceDestroyed(SurfaceHolder holder) {
        Log.d(TAG, "Surface is being destroyed");
        // tell the thread to shut down and wait for it to finish
        // this is a clean shutdown
        boolean retry = true;
        while (retry) {
            try {
                thread.join();
                retry = false;
            } catch (InterruptedException e) {
                // try again shutting down the thread
            }
        }
        Log.d(TAG, "Thread was shut down cleanly");
    }

    public void render(Canvas canvas) {
        canvas.drawColor(Color.TRANSPARENT);
        droid.draw(canvas);
        butt.draw(canvas);
        butt1.draw(canvas);
        butt2.draw(canvas);
        butt3.draw(canvas);
        buttz.draw(canvas);
        buttz1.draw(canvas);
        buttz2.draw(canvas);
        buttz3.draw(canvas);
        buttx.draw(canvas);
    }
    /**
     * This is the game update method. It iterates through all the objects
     * and calls their update method if they have one or calls specific
     * engine's update method.
     */
    public void update() {
        droid.update();
        }
    public void handleActionDown(int eventX, int eventY) {
          if (eventX >= (butt.x - butt.bitmap.getWidth() / 2) && (eventX <= (butt.x + butt.bitmap.getWidth()/2))) {
           if (eventY >= (buttz.y - buttz.bitmap.getHeight() / 2) && (eventY <= (buttz3.y + buttz3.bitmap.getHeight() / 2))) {
            // droid touched
            droid.setTouched(true);
           } else {
               droid.setTouched(false);
           }
          } else {
               droid.setTouched(false);
           } 
              if (eventX >= (buttz1.x - buttz1.bitmap.getWidth() / 2) && (eventX <= (buttz.x + buttz.bitmap.getWidth()/2))) {
               if (eventY >= (butt1.y - butt1.bitmap.getHeight() / 2) && (eventY <= (butt1.y + butt1.bitmap.getHeight() / 2))) {
                    // droid touched
                    droid.setTouched1(true);
                   } else {
                       droid.setTouched1(false);
                   }
                  }else {
                       droid.setTouched1(false);
                   }
              if (eventX >= (butt2.x - butt2.bitmap.getWidth() / 2) && (eventX <= (butt2.x + butt2.bitmap.getWidth()/2))) {
                   if (eventY >= (buttz1.y - buttz1.bitmap.getHeight() / 2) && (eventY <= (buttz2.y + buttz2.bitmap.getHeight() / 2))) {
                        // droid touched
                        droid.setTouched2(true);
                       } else {
                           droid.setTouched2(false);
                       }
                      }else {
                           droid.setTouched2(false);
                       }
              if (eventX >= (buttz2.x - buttz2.bitmap.getWidth() / 2) && (eventX <= (buttz3.x + buttz3.bitmap.getWidth()/2))) {
                   if (eventY >= (butt3.y - butt3.bitmap.getHeight() / 2) && (eventY <= (butt3.y + butt3.bitmap.getHeight() / 2))) {
                        // droid touched
                        droid.setTouched3(true);
                       } else {
                           droid.setTouched3(false);
                       }
                      }else {
                           droid.setTouched3(false);
                       }

              if (droid.touched & !droid.touched1 & !droid.touched3) {
                  if (!moved) {
                  droid.bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.heror);
                  moved = true;
                  }
                }else {
                    moved = false;
                }if (droid.touched1 & !droid.touched & !droid.touched2){
                     if (!moved1) {
                    droid.bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.herou);
                     moved1 = true;
                     }
                }else {
                    moved1 = false;
                } if (droid.touched2 & !droid.touched1 & !droid.touched3){
                     if (!moved2) {
                         droid.bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.herol);
                    moved2 = true;
                 }
            }else {
                moved2 = false;
            } if (droid.touched3 & !droid.touched2 & !droid.touched){
                if (!moved7) {
                    droid.bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.herod);
                    moved7 = true;
             }
        }else {
            moved7 = false;
        } if (droid.touched & droid.touched1){
                    if (!moved3) {
                        droid.bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.herour);
                    moved3 = true;
                 }
            }else {
                moved3 = false;
            } if (droid.touched1 & droid.touched2){
                if (!moved4) {
                    droid.bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.heroul);
                    moved4 = true;
             }
        }else {
            moved4 = false;
        } if (droid.touched2 & droid.touched3){
            if (!moved5) {
                droid.bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.herodl);
                    moved5 = true;
         }
    }else {
        moved5 = false;
    } if (droid.touched3 & droid.touched){
        if (!moved6) {
            droid.bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.herodr);
                    moved6 = true;
     }
}else {
    moved6 = false;
}

         }
}

/**
 * 
 */
package com.workspace.pockethero.model;
import android.graphics.Bitmap;
import android.graphics.Canvas;
/**
 * This is a test droid that is dragged, dropped, moved, smashed against
 * the wall and done other terrible things with.
 * Wait till it gets a weapon!
 * 
 * @author impaler
 *
 */
public class Droid {
    public Bitmap bitmap;   // the actual bitmap
    public int x;           // the X coordinate
    public int y;           // the Y coordinate
    public boolean touched; // if droid is touched/picked up
    public boolean touched1;    // if droid is touched/picked up
    public boolean touched2;    // if droid is touched/picked up
    public boolean touched3;    // if droid is touched/picked up
    public Droid(Bitmap bitmap, int x, int y) {
        this.bitmap = bitmap;
        this.x = x;
        this.y = y;
        }
    public Bitmap getBitmap() {
        return bitmap;
    }
    public void setBitmap(Bitmap bitmap) {
        this.bitmap = bitmap;
    }
    public int getX() {
        return x;
    }
    public void setX(int x) {
        this.x = x;
    }
    public int getY() {
        return y;
    }
    public void setY(int y) {
        this.y = y;
    }

    public void draw(Canvas canvas) {
        canvas.drawBitmap(bitmap, x - (bitmap.getWidth() / 2), y - (bitmap.getHeight() / 2), null);
    }
    /**
     * Method which updates the droid's internal state every tick
     */
    public void setTouched(boolean touched) {
        this.touched = touched;
    }
public boolean isTouched() {
    return touched;
}
public void setTouched1(boolean touched) {
    this.touched1 = touched;
}
public boolean isTouched1() {
return touched1;
}
public void setTouched2(boolean touched) {
    this.touched2 = touched;
}
public boolean isTouched2() {
return touched2;
}
public void setTouched3(boolean touched) {
    this.touched3 = touched;
}
public boolean isTouched3() {
return touched3;
}
    public void update() {
        if (touched & !touched1 & !touched3) {
            x += 1;
        }else if (touched1 & !touched & !touched2){
            y -= 1;
        }else if (touched2 & !touched1 & !touched3){
            x -= 1;
        }else if (touched3 & !touched2 & !touched){
            y += 1;
        }else if (touched & touched1){
            x += 1;
            y -= 1;
        }else if (touched1 & touched2){
            x -= 1;
            y -= 1;
        }else if (touched2 & touched3){
            x -= 1;
            y += 1;
        }else if (touched3 & touched){
            x += 1;
            y += 1;
        }
    }
    /**
     * Handles the {@link MotionEvent.ACTION_DOWN} event. If the event happens on the 
     * bitmap surface then the touched state is set to <code>true</code> otherwise to <code>false</code>
     * @param eventX - the event's X coordinate
     * @param eventY - the event's Y coordinate
     */
}

还为每个按钮创建了其他类,但我没有将它们粘贴在这里,因为它们实际上与droid.java

相同。

在每个循环中重新绘制整个帧是绘制/移动精灵和使用画布执行任何操作的正确方法。

缓冲区每一帧被清除,你需要在指定位置重新绘制背景和所有对象。

在你的代码中,render()和update()的调用频率不会超过大约每16毫秒一次~(每秒60帧),所以你所要考虑的就是绘制屏幕上的场景。

我不确定你所说的"滞后"是什么意思,也许你有一个与你的位图或手机性能大小有关的性能问题,但我希望这是接近你所寻找的。

最新更新