简体   繁体   English

java arrayList不同地对待不同元素

[英]java arrayList treating different elements differently

So, I'm trying to make a simple platformer, here is the code: 因此,我正在尝试制作一个简单的平台游戏,代码如下:

package Main;

import java.applet.Applet;
import java.awt.Color;
import java.awt.Font;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;

public class Platformer extends Applet implements Runnable, KeyListener{

    // buffering variables
    private Image dbImage;
    private Graphics dbg;

    // running boolean
    private boolean running = true;

    // Player coords
    private int rectX = 100;
    private int rectY = 420;

    // initialise dx and dy at zero
    private double dx = 0;
    private double dy = 0;

    private boolean jumping = false;

    //debug Strings
    private String inter = new String();
    private String coords = new String();

    //for background scrolling
    private int worldShift;

    //sprites
    Rectangle2D player = new Rectangle2D.Double(rectX, rectY, 10, 10);
    Rectangle2D ground = new Rectangle2D.Double(0, 420, 800, 150);
    int[][] platforms = { {300 + worldShift, 300, 100, 20}, { 450 + worldShift, 200, 100, 20 },     { 500 + worldShift, 250, 100, 20 }, { 100 + worldShift, 200, 100, 20 } };
    ArrayList<Rectangle2D> platformList = new ArrayList<Rectangle2D>();

    int level = 1;

    @Override
    public void init() {

        setSize(800, 480);
        setFocusable(true);
        addKeyListener(this);
        Frame frame = (Frame) this.getParent().getParent();
        frame.setTitle("Test");
        setVisible(true);

        for (int i = 0; i < platforms.length; i++){
            // platforms
            Rectangle2D platform = new Rectangle2D.Double();
            platform.setRect(platforms[i][0] + worldShift, platforms[i][1], platforms[i][2], platforms[i][3]);
            platformList.add(0, platform);
        }
    }

    @Override
    public void start() {
        Thread thread = new Thread(this);
        thread.start();
    }

    @Override
    public void stop() {
        // TODO Auto-generated method stub
    }

    @Override
    public void destroy() {
        // TODO Auto-generated method stub
    }

    public void paint(Graphics g) {
        //Double Buffering
        Graphics2D g2 = (Graphics2D) g;
        dbImage = createImage(getWidth(), getHeight());
        dbg = dbImage.getGraphics();
        paintComponent(dbg);
        g2.drawImage(dbImage, 0, 0, this);
    }

    // Paint objects
    public void paintComponent(Graphics g) {
        Graphics2D g2 = (Graphics2D) g;

        g2.setColor(Color.white);
        g2.draw(player);
        g2.fill(player);

        if (level == 1) {
            g2.setColor(Color.blue);
            g2.draw(ground);
            g2.fill(ground);

            for (Rectangle2D plat : platformList){
                g2.setColor(Color.red);
                g2.draw(plat);
                g2.fill(plat);
            }

            //debug printouts
            g.drawString(inter, 400, 30);
            g.drawString(coords, 20, 150);

            Font bold = new Font("Liberation Sans", Font.BOLD, 36);
            setFont(bold);
            g.drawString("dx, dy: (" + dx + ", " + dy + ")", 30, 30);
            g.drawString("x, y: (" + player.getX() + ", " + player.getY() + ")", 30, 60);
        }
    }

    @Override
    public void run() {
        while (running) {

            update();
            repaint();

            try {
                Thread.sleep(17);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public void update() {
        worldShift = 0;

        rectX += dx;
        rectY += dy + 1;

        // set sprite coords
        player.setRect(rectX, rectY, 10, 10);
        ground.setRect(0, 420, 800, 480);

        // stops player running off screen
        if (rectX < 1)  rectX = 0;
        if (rectX > 790) rectX = 790;

        // collision detection
        if (player.intersects(ground)) {
            rectY = (int) (ground.getY() - player.getHeight());
            jumping = false;
            dy = 0;
        }

        for (int i = 0; i < platformList.size(); i++){
            Rectangle2D plat = platformList.get(i);

            //sets platform's coordinates
            plat.setRect(plat.getX() + worldShift, plat.getY(), plat.getWidth(), plat.getHeight());

            //sets debug Strings
            coords = "Not on platform";
            inter = " " + player.intersects(plat);

            //for moving the world
            if (rectX > 700 && dx == 5)
                worldShift = -5;
            if (rectX < 100 && dx == -5)
                worldShift = 5;

            //collision detection
            if (player.intersects(plat)) {
                System.out.println(plat);
                jumping = false;
                dy = 0;
                coords = " " + plat.getBounds();
                System.out.println(platformList.indexOf(plat));
                // if player coming from top
                if (rectY < plat.getY())
                    rectY = (int) (plat.getY() - player.getHeight());
                    // if player coming from bottom
                else if (rectY > plat.getY() + plat.getHeight())
                    rectY = (int) (plat.getY() + plat.getHeight());
            }
            else if (!player.intersects(plat) && !player.intersects(ground)) jumping = true;
        }

        //implements falling
        if (jumping)
            dy += 1;
    }

    //button presses
    @Override
    public void keyPressed(KeyEvent e) {
        System.out.println("Key pressed code=" + e.getKeyCode() + ", char="+ e.getKeyChar());
        if (e.getKeyCode() == 37)
            dx -= 5; // 37 is left
        if (e.getKeyCode() == 39)
            dx += 5; // 39 is right
        // if (e.getKeyCode() == 40) dy -= 5; //40 is down
        if (e.getKeyCode() == 38 && jumping == false){
            // if on the ground,
            // i.e. only jump if on the ground
            dy -= 20; // 38 is up
            jumping = true;
            System.out.println("Jumping");
        }
    }

    //key release
    @Override
    public void keyReleased(KeyEvent e) {
        if (e.getKeyCode() == 37)
            dx = 0; // 37 is left
        if (e.getKeyCode() == 39)
            dx = 0; // 39 is right
        if (e.getKeyCode() == 40)
            dy = 0; // 40 is down
        // if (e.getKeyCode() == 38)
    }

    @Override
    public void keyTyped(KeyEvent e) {
        // TODO Auto-generated method stub

    }

}

The problem is that when the player jumps on the platforms, the platforms act differently depending on the platform. 问题在于,当玩家跳上平台时,平台的行为会因平台而异。 If I jump on the last drawn one, it acts how I want (jumping is set to false , the player.intersects(plat) prints true to screen and the platform's bounds are printed both to the screen and the console). 如果我跳到最后绘制的一个,它将按照我想要的方式运行(跳转设置为falseplayer.intersects(plat)在屏幕上显示为true,平台的边界在屏幕和控制台上都显示)。 Then, when I jump on a different platform, jumping stays true, player.intersects(plat) prints false to screen and the platform's bounds are only printed to the console, not the screen. 然后,当我跳到另一个平台上时,跳动保持为true, player.intersects(plat)在屏幕上打印false,并且平台的边界仅打印到控制台,而不是屏幕。

I think I've narrowed it down to being something to do with having more than one element in the arrayList, but I don't know the specific issue. 我想我已将其范围缩小到与arrayList中具有多个元素有关的事情,但是我不知道具体问题。

there is a simple reason why jump is always true - in the last line of your complex logic you write 跳转始终为真有一个简单的原因-在您编写的复杂逻辑的最后一行中

 if (!player.intersects(plat) && !player.intersects(ground)) jumping = true;

This will overwrite the jumping=false you set in a loop run before. 这将覆盖您之前在循环运行中设置的jumping=false

If you intersect with a platform which is not the last then you will not intersect with the last platform in the ArrayList - but the logic code above will set jump to true in the last loop run. 如果您与不是最后一个平台的平台相交,那么您将不会与ArrayList中的最后一个平台相交-但上面的逻辑代码将在最后一次循环运行中将jump设置为true。

I assume your player is only intersecting one platform at once - so your code should work if you insert a break statement after the last operation in the if(player.intersects(plat)) { ... } code block. 我假设您的播放器一次仅与一个平台相交-因此,如果您在if(player.intersects(plat)) { ... }代码块中的最后一个操作之后插入break语句,则您的代码应该可以工作。

You should reengineer your logic part and write JUnit tests for it - but anyway you should refactor your code. 您应该重新设计逻辑部分并为其编写JUnit测试-但是无论如何,您都应该重构代码。 If your game is getting more complex you will get problems with adapting new features. 如果您的游戏变得越来越复杂,那么使用新功能会遇到问题。 Please use constants for the key codes so that it is more easy for readers to understand what you are doing. 请使用常数作为键码,以使读者更容易理解自己在做什么。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM