gpt4 book ai didi

java - 以编程方式循环从上到下移动 ImageView,在屏幕外开始和结束

转载 作者:行者123 更新时间:2023-12-02 00:40:28 26 4
gpt4 key购买 nike

我正在制作一个小型 Android 游戏,其中需要两个 ImageView(障碍物)同时从屏幕顶部移动到屏幕底部;开始和结束于屏幕的外部。这样做将是一个开始。

我有一个计时器,每次计时器结束时,它都会再次运行,我还希望另外两个 ImageView(与前两个相同)以上述相同的方式移动。

换句话说:

  • 某些随机事件会触发计时器
  • 计时器达到阈值 -> 计时器重置并且两个 ImageView 开始下降

我已经得到了一些作品,但是具有位图和 Y 增量。问题是,由于手机的增量速度尽可能快,游戏可能会变得滞后,并且两个图像下降的速度在两部不同的手机上不会相同。

我知道我必须使用动画,但每次尝试使用它们时我都无法得到我想要的东西。它们通常不会从我想要的地方开始,并且会发生奇怪的事情。

以下是我已经访问过的一些链接:

这里有一些代码向您展示我所拥有的内容:

游戏 View

public class GameView extends SurfaceView implements SurfaceHolder.Callback {
// [...]

@Override
public void surfaceCreated(SurfaceHolder surfaceHolder) {
// [...]
this.obstacles = new ArrayList <> ();

this.handleObstacleTimer = null;
this.runnableObstacleTimer = null;
}


@Override
public boolean onTouchEvent(MotionEvent event) {
// [...]
switch (event.getAction()) {
case MotionEvent.ACTION_UP:
this.startObstacleTimer();
GameLogic.gameState = GameState.RUNNING;
// [...]
}

return result;
}


@Override
public void draw (Canvas canvas) {
super.draw(canvas);

if (canvas != null) {
this.background.draw(canvas);
if (! this.obstacles.isEmpty()) {
for (Obstacle obstacle : this.obstacles) {
obstacle.draw(canvas);
}
}
// [...]
}
}


public void createObstacle () {
Bitmap imageObstacle = BitmapFactory.decodeResource(this.getResources(), R.drawable.obstacle);
this.obstacles.add(new Obstacle(imageObstacle, this, this.displayMetrics.widthPixels, this.displayMetrics.heightPixels));
}

public void removeObstacle (Obstacle obstacle) {
this.obstacles.remove(obstacle);
}

private void stopObstacleTimer () {
if (this.handleObstacleTimer != null && this.runnableObstacleTimer != null) {
this.handleObstacleTimer.removeCallbacks(this.runnableObstacleTimer);
this.handleObstacleTimer = null;
}
}

private void startObstacleTimer () {
if (this.handleObstacleTimer == null) {
final Handler handler = new Handler();
this.runnableObstacleTimer = new Runnable() {
@Override
public void run() {
if (GameLogic.gameState == GameState.RUNNING) {
createObstacle();
handler.postDelayed(this, 2700);
}
}
};

handler.postDelayed(this.runnableObstacleTimer, 2700);

this.handleObstacleTimer = handler;
}
}

// [...]

// Called by a custom Thread class
public void update () {
if (! this.obstacles.isEmpty()) {
for (Obstacle obstacle : this.obstacles) {
obstacle.update();
}
}
// [...]
}
}

MAINTHREAD(自定义线程类)

public class MainThread extends Thread {

private SurfaceHolder surfaceHolder;
private GameView gameView;
private GameLogic gameLogic;

private boolean running;

public static Canvas canvas;


public MainThread (SurfaceHolder surfaceHolder, GameView gameView, GameLogic gameLogic) {
super();

this.surfaceHolder = surfaceHolder;
this.gameView = gameView;
this.gameLogic = gameLogic;
}


@Override
public void run() {
while (this.running) {
this.canvas = null;

try {
this.canvas = this.surfaceHolder.lockCanvas();
synchronized (this.surfaceHolder) {
this.gameView.update();
this.gameView.draw(this.canvas);
this.gameLogic.update();
}
} catch (Exception e) {

} finally {
if (this.canvas != null) {
try {
this.surfaceHolder.unlockCanvasAndPost(this.canvas);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}


public void setRunning (boolean isRunning) {
this.running = isRunning;
}
}

障碍

public class Obstacle {

private static final int GAP_MIN_X = 300;
private static int GAP_MAX_X;
private static final int GAP_WIDTH = 250;

private GameView gameView;

private int displayHeight;

private Bitmap obstacleLeft;
private Bitmap obstacleRight;
private int leftX;
private int rightX;
private int y;

private boolean passed;


public Obstacle (Bitmap image, GameView gameView, int displayWidth, int displayHeight) {
this.gameView = gameView;

this.displayHeight = displayHeight;

this.obstacleLeft = this.flip(image);
this.obstacleRight = image;

GAP_MAX_X = displayWidth - GAP_MIN_X;
final int randomX = new Random().nextInt((GAP_MAX_X - GAP_MIN_X) + 1) + GAP_MIN_X;

this.leftX = randomX - this.obstacleLeft.getWidth() - (GAP_WIDTH / 2);
this.rightX = randomX + (GAP_WIDTH / 2);

this.y = 0 - this.obstacleLeft.getHeight();

this.passed = false;
}


private Bitmap flip (Bitmap image) {
Matrix m = new Matrix();
m.preScale(-1, 1);
Bitmap result = Bitmap.createBitmap(image, 0, 0, image.getWidth(), image.getHeight(), m, false);
result.setDensity(DisplayMetrics.DENSITY_DEFAULT);
return result;
}


/**
* Those getters are used for collision
*/
public int getLeftX () {
return this.leftX;
}

public int getRightX () {
return this.rightX;
}

public int getY () {
return this.y;
}

public int getWidth () {
return this.obstacleLeft.getWidth();
}

public int getHeight () {
return this.obstacleLeft.getHeight();
}


public boolean hasPassed () {
return this.passed;
}

public void setAsPassed () {
this.passed = true;
}


public void draw (Canvas canvas) {
canvas.drawBitmap(this.obstacleLeft, this.leftX, this.y, null);
canvas.drawBitmap(this.obstacleRight, this.rightX, this.y, null);
}


public void update () {
if (! (GameLogic.gameState == GameState.GAMEOVER)) {
this.y += 8;

if (this.y > this.displayHeight) {
this.gameView.removeObstacle(this);
}
}
}
}

基本上,我想要的是得到相同的结果。但无论游戏在哪款手机上运行,​​都没有延迟,并且障碍物以相同的速度移动。

最佳答案

如果在 Obstacle.update() 函数中,将 Y 增量从常量整数 8 更改为与调用更新函数的时间间隔成正比的值,则在任何设备上速度都相同。例如,您可以根据上次 update() 调用和当前 update 调用的时间之间的差异来计算变化

long speed = 100; //you should add this to adjust the speed of the incrementing
long delta = System.currentTimeMillis();
public void update () {
delta = speed*(System.currentTimeMillis() - delta);
if (! (GameLogic.gameState == GameState.GAMEOVER)) {
this.y += delta;

if (this.y > this.displayHeight) {
this.gameView.removeObstacle(this);
}
}
}

这样,您的 delta 变量将随着上次调用和当前调用之间的时间间隔而变化,因为 System.currentTimeMillis() 返回以毫秒为单位的当前时间

关于java - 以编程方式循环从上到下移动 ImageView,在屏幕外开始和结束,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57946024/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com