0

由于我一直在移植使用xda 开发站点上的教程制作的 java 小程序,因此遇到了许多问题。我一直在尝试将事情一一解决,以尽量减少错误。这个碰撞检测问题已被证明是我无法解决的问题。它应该工作的方式是在主要精灵发射的子弹上以及敌人周围放置矩形。当矩形相交时,子弹应该消失并且敌人应该死亡。

有些东西告诉我 android 的矩形函数在这里可能是一个问题。如此链接所示,有四种不同的交叉点测试。我为碰撞检测系统编写的代码与教程中使用的代码基本相同。另外,我什至不确定矩形是否在正确的位置,如果它们在屏幕上,因为我无法使用“drawRect”函数绘制矩形。元组值应该是正确的,因为所有内容都是从桌面游戏版本复制的。

编辑:所有内容都是从桌面版本复制的,但我不得不更改与矩形有关的所有内容,因为我不能再使用 java.awt.Rectangle。所有与矩形相关的代码都使用 android.graphics.Rect。

tl;dr:从 java 小程序到 android 应用程序的碰撞检测将不起作用。

这是移植的代码:

package com.kilobolt.robotgame;

import android.graphics.Rect;

public class Projectile {

    private int x, y, speedY;
    private boolean visible;

    private Rect r;

    public Projectile(int startX, int startY) 
    {
        x = startX;
        y = startY;
        speedY = 7;
        visible = true;

        r = new Rect(0,0,0,0);
    }

    public void update()
    {
        y -= speedY;
        r.set(x, y, 4, 10);
        if (y < 0) {
           visible = false;
           r=null;
        }
        if (visible){
            checkCollision();
        }
    }

    private void checkCollision()
    {
        if(Rect.intersects(r, GameScreen.xguy1.xrect1) && GameScreen.xguy1IsAlive == true)
        {
        visible = false;
        GameScreen.score += 10;
        GameScreen.xguy1IsAlive = false;
        System.out.println("1st enemy Collision");
        }
        else if(Rect.intersects(r, GameScreen.xguy2.xrect2) && GameScreen.xguy2IsAlive == true)
        {
            visible = false;
            GameScreen.score += 10;
            GameScreen.xguy2IsAlive = false;
            System.out.println("2nd enemy Collision - RIGHT");
        }
        else if(Rect.intersects(r, GameScreen.xguy3.xrect3) && GameScreen.xguy3IsAlive == true)
        {
            visible = false;
            GameScreen.score += 10;
            GameScreen.xguy3IsAlive = false;
            System.out.println("3rd enemy Collision");
        }

        if(GameScreen.xguy1IsAlive == false && GameScreen.xguy2IsAlive == false 
                && GameScreen.xguy3IsAlive == false)
        {
            GameScreen.allEnemiesAreDead = true;
        }

//      if(r.intersect(GameScreen.saucer.sRect))
//      {
//          visible = false;
//          GameScreen.score += 100;
//          GameScreen.saucerIsAlive = false;
//          System.out.println("you hit the alien!");
//      }

    }


    public int getX() {
        return x;
    }

    public int getY() {
        return y;
    }

    public int getSpeedY() {
        return speedY;
    }

    public boolean isVisible() {
        return visible;
    }

    public void setX(int x) {
        this.x = x;
    }

    public void setY(int y) {
        this.y = y;
    }

    public void setSpeedY(int speedY) {
        this.speedY = speedY;
    }

    public void setVisible(boolean visible) {
        this.visible = visible;
    }

}

..................................................... .

package com.kilobolt.robotgame;

import android.graphics.Rect;
import java.util.ArrayList;

public class Enemy 
{
    private int maxHealth, currentHealth, power, speedX, speedY, centerX, centerY;
    private Background bg = GameScreen.getBg1();
    public  Rect xrect1 = new Rect(0,0,0,0);
    public  Rect xrect2 = new Rect(0,0,0,0);
    public  Rect xrect3 = new Rect(0,0,0,0);
    private boolean isMovingRight = true;
    private boolean isMovingLeft = false;
    private boolean xguy1IsShooting = false;
    private boolean xguy2IsShooting = false;
    private boolean xguy3IsShooting = false;
//  private ArrayList<EnemyProjectile> eProjectiles = new ArrayList<EnemyProjectile>();

    //Behavioral Methods
    public void update() {
    //centerX += speedY;
    //moveRight();
    //moveLeft();
    //changeMovement();
    //autoFire();
    speedY = bg.getSpeedY();
    speedX = 1;
    //setBounds??? 
    xrect1.set(centerX + 74, centerY - 18, 14, 14);
    xrect2.set(centerX + 134, centerY - 18, 14, 14); 
    xrect3.set(centerX + 19 , centerY - 18, 14, 14);
    }

//  public void autoFire()
//  {
//      int num = 1 + (int)(Math.random() * ((250 - 1) + 1));
//      //System.out.println(num);
//      if(num == 4 || num == 6 || num == 8 && xguy1IsShooting == false)
//      {
//          if(GameScreen.xguy1IsAlive == true)
//          {
//              //xguy1Attack();
//          }
//      }
//      if(num == 1 || num == 3 || num == 5 && xguy2IsShooting == false)
//      {
//          if(GameScreen.xguy2IsAlive == true)
//          {
//              //xguy2Attack();
//          }
//      }
//      if(num == 12 || num == 15 || num == 17 && xguy3IsShooting == false)
//      {
//          if(GameScreen.xguy3IsAlive == true)
//          {
//              //xguy3Attack();
//          }
//      }
//  }

    public void moveRight()
    {
        if(isMovingRight == true)
        {
            centerX += speedX;
            if(centerX >= 630)
            {
                isMovingRight = false;
                isMovingLeft = true;
            }
        }
    }
    public void moveLeft()
    {
        if(isMovingLeft == true)
        {
            centerX -= speedX;
            if(centerX <= 10)
            {
                isMovingLeft = false;
                isMovingRight = true;
            }
        }
    }
    public void changeMovement()
    {
        //causes delayed death - xguys only die after going right
        if(centerX >= 630)
        {
            isMovingRight = false;
        }
        if(isMovingRight == false)
        {
            isMovingLeft = true;
        }
    }
    public void die() 
    {

    }
//  public void xguy1Attack() 
//  {
//      EnemyProjectile e = new EnemyProjectile(centerX - 10, centerY - 6);
//      eProjectiles.add(e);
//      xguy1IsShooting = false;
//  }
//  public void xguy2Attack()
//  {
//      EnemyProjectile e = new EnemyProjectile(centerX + 50, centerY - 6);
//      eProjectiles.add(e);
//      xguy2IsShooting = false;
//  }
//  
//  public void xguy3Attack()
//  {
//      EnemyProjectile e = new EnemyProjectile(centerX - 70, centerY - 6);
//      eProjectiles.add(e);
//      xguy3IsShooting = false;
//  }

    public int getMaxHealth() {
        return maxHealth;
    }

    public int getCurrentHealth() {
        return currentHealth;
    }

    public int getPower() {
        return power;
    }

    public int getSpeedY() {
        return speedY;
    }

    public int getCenterX() {
        return centerX;
    }

    public int getCenterY() {
        return centerY;
    }

    public Background getBg() {
        return bg;
    }

    public void setMaxHealth(int maxHealth) {
        this.maxHealth = maxHealth;
    }

    public void setCurrentHealth(int currentHealth) {
        this.currentHealth = currentHealth;
    }

    public void setPower(int power) {
        this.power = power;
    }

    public void setSpeedX(int speedX) {
        this.speedY = speedX;
    }

    public void setCenterX(int centerX) {
        this.centerX = centerX;
    }

    public void setCenterY(int centerY) {
        this.centerY = centerY;
    }

    public void setBg(Background bg) {
        this.bg = bg;
    }

//  public ArrayList getEProjectiles() {
//      return eProjectiles;
//      }
}

..................................................... ......

package com.kilobolt.robotgame;

import com.kilobolt.robotgame.BasicEnemy;

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

import android.graphics.Color;
import android.graphics.Paint;

import com.kilobolt.framework.Game;
import com.kilobolt.framework.Graphics;
import com.kilobolt.framework.Image;
import com.kilobolt.framework.Input.TouchEvent;
import com.kilobolt.framework.Screen;

public class GameScreen extends Screen {
    enum GameState {
        Ready, Running, Paused, GameOver
    }

    GameState state = GameState.Ready;

    // Variable Setup

    private static Background bg1, bg2;
    private static Ship ship;
    public static BasicEnemy xguy1, xguy2, xguy3;
//
    private Image character, damaged1, damaged2, background, startScreen, xguy, vxguy, explode1, explode2, explode3, explode4, explode5,
    explode6, explode7, explode8, explode9, explode10, explode11, explode12, xexplode, xexplode2, flyingSaucer;
    private Animation anim, xanim;

    public static int score = 0;
    public static int lives = 3;

    static boolean xguy1IsAlive = true;
    static boolean xguy2IsAlive = true;
    static boolean xguy3IsAlive = true;

    static boolean saucerIsAlive = true;
    static boolean allEnemiesAreDead = false;

    static boolean saucerTime = false;
    static boolean saucerIsMoving = false; 
    static boolean startScreenOn = true;

    Paint paint, paint2;

    public GameScreen(Game game) {
        super(game);

        // Initialize game objects here

        bg1 = new Background(0, 0);
        bg2 = new Background(0, -480);
        ship = new Ship();
        xguy1 = new BasicEnemy(420, 100);
        xguy2 = new BasicEnemy(480, 100);
        xguy3 = new BasicEnemy(360, 100);

        character = Assets.character;
        damaged1 = Assets.character2;
        damaged1 = Assets.character3;

        xguy = Assets.xguy;

        xanim = new Animation();
        xanim.addFrame(xguy, 250);
        xanim.addFrame(vxguy, 250);

        // Defining a paint object
        paint = new Paint();
        paint.setTextSize(30);
        paint.setTextAlign(Paint.Align.CENTER);
        paint.setAntiAlias(true);
        paint.setColor(Color.WHITE);

        paint2 = new Paint();
        paint2.setTextSize(100);
        paint2.setTextAlign(Paint.Align.CENTER);
        paint2.setAntiAlias(true);
        paint2.setColor(Color.WHITE);

    }


    @Override
    public void update(float deltaTime) {
        List<TouchEvent> touchEvents = game.getInput().getTouchEvents();

        if (state == GameState.Ready)
            updateReady(touchEvents);
        if (state == GameState.Running)
            updateRunning(touchEvents, deltaTime);
        if (state == GameState.Paused)
            updatePaused(touchEvents);
        if (state == GameState.GameOver)
            updateGameOver(touchEvents);
    }

    private void updateReady(List<TouchEvent> touchEvents) {

        // This example starts with a "Ready" screen.
        // When the user touches the screen, the game begins.
        // state now becomes GameState.Running.
        // Now the updateRunning() method will be called!

        if (touchEvents.size() > 0)
            state = GameState.Running;
    }

    private void updateRunning(List<TouchEvent> touchEvents, float deltaTime) {

        // This is identical to the update() method

        // 1. All touch input is handled here:
        int len = touchEvents.size();
        for (int i = 0; i < len; i++) {
            TouchEvent event = touchEvents.get(i);
            if (event.type == TouchEvent.TOUCH_DOWN) {

                if (inBounds(event, 735, 415, 65, 65)) {
                    ship.moveRight();
                    ship.setMovingRight(true);
                    System.out.println("sucess");
                }
                if (inBounds(event, 0, 415, 65, 65)) {
                    ship.moveLeft();
                    ship.setMovingLeft(true);
                    System.out.println("sucess");
                }               
                else if (inBounds(event, 0, 350, 65, 65)) {
                    ship.shoot();
                }
                else if (inBounds(event, 735, 350, 65, 65)) {
                    ship.shoot();
                }
//              else if (inBounds(event, 0, 415, 65, 65)
//                      ) {
////                    currentSprite = Assets.characterDown;
////                    robot.setDucked(true);
////                    robot.setSpeedX(0);
//
//              }

                if (event.x > 400) {
                    //...

                }

            }

            if (event.type == TouchEvent.TOUCH_UP) {

                if (inBounds(event, 0, 415, 65, 65)) {
//                  //...

                }
                if (inBounds(event, 735, 415, 65, 65)) {
                    ship.stopRight();
                }
                if (inBounds(event, 0, 415, 65, 65)) {
                    ship.stopLeft();
                }

//              if (inBounds(event, 0, 0, 35, 35)) {
//                  pause();
//
//              }

                if (event.x > 400) {
                    //...
                }
            }

        }

        // 2. Check miscellaneous events like death:
//
//      if (livesLeft == 0) {
//          state = GameState.GameOver;
//      }

        // 3. Call individual update() methods here.
        // This is where all the game updates happen.
        ship.update();

        ArrayList projectiles = ship.getProjectiles();
        for (int i = 0; i < projectiles.size(); i++) {
            Projectile p = (Projectile) projectiles.get(i);
            if (p.isVisible() == true) {
                p.update();
            } else {
                projectiles.remove(i);
            }
        }


        xguy1.update();
        xguy2.update();
        xguy3.update();
        bg1.update();
        bg2.update();
        animate();
//...game over state here...
    }

    private boolean inBounds(TouchEvent event, int x, int y, int width,
            int height) {
        if (event.x > x && event.x < x + width - 1 && event.y > y
                && event.y < y + height - 1)
            return true;
        else
            return false;
    }

    private void updatePaused(List<TouchEvent> touchEvents) {
        int len = touchEvents.size();
        for (int i = 0; i < len; i++) {
            TouchEvent event = touchEvents.get(i);
            if (event.type == TouchEvent.TOUCH_UP) {
                if (inBounds(event, 0, 0, 800, 240)) {

                    if (!inBounds(event, 0, 0, 35, 35)) {
                        resume();
                    }
                }

                if (inBounds(event, 0, 240, 800, 240)) {
                    nullify();
                    goToMenu();
                }
            }
        }
    }

    private void updateGameOver(List<TouchEvent> touchEvents) {
        int len = touchEvents.size();
        for (int i = 0; i < len; i++) {
            TouchEvent event = touchEvents.get(i);
            if (event.type == TouchEvent.TOUCH_DOWN) {
                if (inBounds(event, 0, 0, 800, 480)) {
                    nullify();
                    game.setScreen(new MainMenuScreen(game));
                    return;
                }
            }
        }

    }

    @Override
    public void paint(float deltaTime) {
        Graphics g = game.getGraphics();

        g.drawImage(Assets.background, bg1.getBgX(), bg1.getBgY());
        g.drawImage(Assets.background, bg2.getBgX(), bg2.getBgY());

        ArrayList projectiles = ship.getProjectiles();
        for (int i = 0; i < projectiles.size(); i++) {
            Projectile p = (Projectile) projectiles.get(i);
            g.drawRect(p.getX()-34, p.getY()+10, 4, 10, Color.RED);
        }
//      // First draw the game elements.
//
        g.drawImage(Assets.character, ship.getCenterX() - 24,
                ship.getCenterY() - 24);
        if(xguy1IsAlive == true)
        {
            g.drawImage(xanim.getImage(), xguy1.getCenterX()-16, xguy1.getCenterY()-12);
        }
        if(xguy2IsAlive == true)
        {
            g.drawImage(xanim.getImage(), xguy2.getCenterX()-16, xguy2.getCenterY()-12);
        }
        if(xguy3IsAlive == true)
        {
            g.drawImage(xanim.getImage(), xguy3.getCenterX()-16, xguy3.getCenterY()-12);
        }
        g.drawRect(xguy1.getCenterX() + 74, xguy1.getCenterX() - 18, 14,  14, 0);

        // Example:
        // g.drawImage(Assets.background, 0, 0);
        // g.drawImage(Assets.character, characterX, characterY);

        // Secondly, draw the UI above the game elements.
        if (state == GameState.Ready)
            drawReadyUI();
        if (state == GameState.Running)
            drawRunningUI();
        if (state == GameState.Paused)
            drawPausedUI();
        if (state == GameState.GameOver)
            drawGameOverUI();

    }

    public void animate() {
        //anim.update(10);
        xanim.update(50);
    }

    private void nullify() {

        // Set all variables to null. You will be recreating them in the
        // constructor.
        paint = null;
        bg1 = null;
        bg2 = null;
        ship = null;
        xguy1 = null;
        xguy2 = null;
        xguy3 = null;
//      currentSprite = null;
        character = null;
        damaged1 = null;
        damaged2 = null;
        xguy = null;
        vxguy = null;
//      anim = null;
        xanim = null;

        // Call garbage collector to clean up memory.
        System.gc();

    }

    private void drawReadyUI() {
        Graphics g = game.getGraphics();

        g.drawARGB(155, 0, 0, 0);
        g.drawString("Tap to Start.", 400, 240, paint);

    }

    private void drawRunningUI() {
        Graphics g = game.getGraphics();
        g.drawImage(Assets.right, 735, 415, 0, 0, 65, 65);
        g.drawImage(Assets.left, 0, 415, 0, 0, 65, 65);
        g.drawImage(Assets.reticle, 0, 350, 0, 0, 65, 65);
        g.drawImage(Assets.reticle, 735, 350, 0, 0, 65, 65);
    }

    private void drawPausedUI() {
        Graphics g = game.getGraphics();
        // Darken the entire screen so you can display the Paused screen.
        g.drawARGB(155, 0, 0, 0);
        g.drawString("Resume", 400, 165, paint2);
        g.drawString("Menu", 400, 360, paint2);

    }

    private void drawGameOverUI() {
        Graphics g = game.getGraphics();
        g.drawRect(0, 0, 1281, 801, Color.BLACK);
        g.drawString("GAME OVER.", 400, 240, paint2);
        g.drawString("Tap to return.", 400, 290, paint);

    }

    @Override
    public void pause() {
        if (state == GameState.Running)
            state = GameState.Paused;

    }

    @Override
    public void resume() {
        if (state == GameState.Paused)
            state = GameState.Running;
    }

    @Override
    public void dispose() {

    }

    @Override
    public void backButton() {
        pause();
    }

    private void goToMenu() {
        // TODO Auto-generated method stub
        game.setScreen(new MainMenuScreen(game));

    }

    public static Background getBg1() {
        // TODO Auto-generated method stub
        return bg1;
    }

    public static Background getBg2() {
        // TODO Auto-generated method stub
        return bg2;
    }

    public static Ship getShip() {
        // TODO Auto-generated method stub
        return ship;
    }

}
4

1 回答 1

1

我敢打赌,您的问题是由于 2 个矩形类之间的 API 差异。

比较android.graphics.Rectjava.awt.Rectangle我看到了一些差异,例如方法参数的含义。

例如,android Rect 使用 left 和right而 awt Rectangle 使用 left 和width

在您调用的类Projectile函数中的代码中,我很确定您将宽度和高度作为最后一个参数而不是右和下传递。updater.set(..)

所以你现有的代码:

r.set(x, y, 4, 10);

应移植到:

r.set(x, y, x+4, y+10);
于 2013-07-21T10:25:40.897 回答