简体   繁体   English

Java 2D Platformer-一些逻辑/物理怪癖

[英]Java 2D Platformer - Some Logic/Physics Quirks

I am making a Java 2d platformer, and am using threads, so far I have 4 classes: 我正在制作Java 2d平台程序,并且正在使用线程,到目前为止,我有4个类:

Main.java -Handles the main JFrame Main.java-处理主JFrame

Board.java -Where most of the game logic is -Using thread that refreshes every 5 milliseconds -KeyListener Board.java-大多数游戏逻辑是-使用每5毫秒刷新一次的线程-KeyListener

Guy.java -Where the instance of guy is made -Using ImageIcon, getting image of guy -other things like getBounds, getX/Y, etc. useful functions Guy.java-在何处创建了Guy的实例-使用ImageIcon,获取Guy的图像-其他诸如getBounds,getX / Y等有用的功能

Platform.java -Where a platform instance is initiated -Again, the useful functions Platform.java-启动平台实例的位置-再次,有用的功能

Now, on to what I have working: 现在,继续我的工作:

I am able to move from platform to platform, and am able to jump. 我能够从一个平台移动到另一个平台,并且能够跳跃。 Here is my gravity code, to check need for gravity, and do it if needed 这是我的重力代码,用于检查重力需求,并在需要时进行

if(guy.getGravityState() == true) {
        //check need for gravity
        boolean colliding = false;
        for(int a = 0; a < platform.length; a++) {
            if(guy.getBounds().intersects(platform[a].getBounds())) {
                colliding = true;
                //guy.setY(platform[a].getY()-platform[a].getHeight()+3);
            }
        }

        //if needed, do gravity
        if(colliding == false) {
            guy.setYSpeed(3);
                            //move him down by positive y speed
        } else {
            guy.setYSpeed(0);
        }
}

Here is how the character moves: 角色移动方式如下:

if(guy.getXSpeed() > 0 && guy.getX() > 500) {
        for(int i = 0; i < platform.length; i++) {
            platform[i].setX(platform[i].getX() - guy.getXSpeed());
        }
    } else if (guy.getXSpeed() < 0 && guy.getX() < 300) {
        for(int i = 0; i < platform.length; i++) {
            platform[i].setX(platform[i].getX() - guy.getXSpeed());
        }
    } else {
        guy.moveX();
    }

    if(guy.getYSpeed() > 0 && guy.getY() > 350) {
        for(int i = 0; i < platform.length; i++) {
            platform[i].setY(platform[i].getY() - guy.getYSpeed());
        }
    } else if  (guy.getYSpeed() < 0 && guy.getY() < 250) {
        for(int i = 0; i < platform.length; i++) {
            platform[i].setY(platform[i].getY() - guy.getYSpeed());
        }
    } else {
        guy.moveY();
    }

Sorry for the lack of comments there, basically it checks if it needs to move the guy, or the platform. 很抱歉在这里没有评论,基本上它会检查是否需要移动此人或平台。 If it is close to the edges, it will move the platforms, it if isnt, the guy will be moved. 如果靠近边缘,它将移动平台;如果不靠近,则将移动该家伙。

Now, jump code (not sure if relevant): 现在,跳转代码(不确定是否相关):

if(guy.getGravityState() == false) {
        d++;
        if(d == 35) {
            d = 0;
            guy.setGravityState(true);
        }
    }

The only way gravity can be turned off is with jump, so if the gravity is off, I used setYSpeed(-5); 可以关闭重力的唯一方法是跳跃,因此如果关闭重力,则使用setYSpeed(-5); so the character would move up (negative number) now it moves up until d = 35, so 35 refreshes. 因此角色现在将向上移动(负数),直到d = 35为止,因此35刷新。 after this point, the gravity is put back to normal. 此后,重力将恢复正常。

So now I hope you stuck around, and can get on to my questions. 所以现在我希望你能坚持下去,并继续回答我的问题。 Take a look on how the game looks at run time: 看一下游戏在运行时的外观:

在此处输入图片说明

Now, when I move right, the character moves down, as wanted, but when I move left, he goes through the platform. 现在,当我向右移动时,角色会根据需要向下移动,但是当我向左移动时,他会穿过平台。 How would I make it so it will not move if there is something stopping it? 我将如何制造它,以便在有东西停止时它不会移动? For example look here, the guy goes right through: 例如看这里,那个家伙会正确地通过:

在此处输入图片说明

My second question is, it is relevant to the first one, when my character jumps, and hits a platform above him, I want it to go straight down, not through the platform. 我的第二个问题是,与第一个问题有关,当我的角色跳跃并撞到他上方的平台时,我希望它直接向下而不是通过平台。

Also, when I jump from something above and just to the left/right, he will sometimes even get stuck as so: 另外,当我从上方跳到左/右时,他有时甚至会被卡住:

在此处输入图片说明

Those are all my questions for now, I very much appreciate if you even help me a little, I know this might be an overwhelming question but any help at all is appreciated. 这些都是我现在所有的问题,如果您能帮助我,我将非常感激,我知道这可能是一个压倒性的问题,但是对您的任何帮助都是值得的。 Thank you. 谢谢。

Looks like you're doing the collision check in your gravity function that stops the player falling through the ground, but there's no collision detection happening when processing the player's movement (either left/right or up from jumping). 看起来您正在重力功能中进行碰撞检查,以阻止玩家跌落地面,但是在处理玩家的运动(向左/向右或从跳跃向上移动)时,没有发生碰撞检测。 That's the issue with both of your problems. 这就是你们两个问题的问题。

When moving the player, you need to work out if his next movement will collide with anything. 移动播放器时,您需要确定下一个动作是否会与任何东西发生碰撞。 You should move the collision detection you have at the moment outside of your gravity function, and handle it in the player's movement function--actually, since the player will continuously be moved as long as his Y speed is set according to your implementation, you might not even need to have gravity running in a loop... Just set the player's Y speed to 3 whenever he isn't jumping. 您应该将当前具有的碰撞检测移动到重力功能之外,并通过播放器的移动功能来处理它-实际上,只要根据您的实现设置了他的Y速度,播放器就会连续移动。甚至可能不需要重力就可以循环运行...只要将玩家不跳动的Y速度设置为3。

I won't attempt to show you what I mean there because I can't see enough of your code to tell how jumping works, but hopefully this answer is enough to put you on the right track. 我不会尝试向您展示我的意思,因为我看不到足够的代码来说明跳跃的工作原理,但是希望这个答案足以使您走上正确的道路。

Note that this is just a rough guide, and you will have other considerations since you're moving platforms around, and may have to change this depending on how you're handling jumping etc. 请注意,这只是一个粗略的指南,由于要移动平台,您还需要考虑其他因素,并且可能必须根据您处理跳跃等的方式来更改此设置。

This also isn't taking account for the fact that the guy might try to fall 3 pixels down, but the ground is 2 pixels away--in this case he would levitate 2 pixels above the block because canExecuteMove is always going to return false. 这也没有考虑到这个人可能会尝试将像素下降3个像素,但地面要相距2个像素,在这种情况下,他会在块上方悬浮2个像素,因为canExecuteMove总是会返回false。

Hope this helps a little. 希望这有所帮助。 :) If you get stuck you should have a read up on ways to handle simple collision detection. :)如果卡住了,您应该阅读一下处理简单碰撞检测的方法。 I haven't done much of this myself but I'm sure someone else might be able to link you to a useful tutorial. 我自己并没有做很多事情,但是我敢肯定其他人也许可以将您链接到有用的教程。

EDIT: Whoops, this won't really fix your second problem with making the guy fall back down after bumping his head very nicely. 编辑:哎呀,这不会真正解决您的第二个问题,使这个家伙很好地撞了头后倒下了。 With my suggestion below he'll stick to the bottom of ceiling until he's finished jumping, then start falling again. 根据我的建议,他将坚持在天花板的底部,直到完成跳跃,然后再次开始下降。 Clearly you need to make sure his jump finishes after he collides with a ceiling (causing him to start dropping again immediately) but the question is "where is the best place to do that?" 显然,您需要确保他与天花板碰撞后跳完(导致他立即开始再次下降),但问题是“这样做的最佳位置在哪里?” I'm out of time so I'll leave that up to you or someone else! 我没时间了,我将把它留给您或其他人!

private void move()
{
    //....your other code
    if(canExecuteMovement(guy.getBounds(), guy.getXSpeed(), 0))
    {
        guy.moveX();
    }

    if(canExecuteMovement(guy.getBounds(), 0, guy.getYSpeed())
    {
        guy.moveY();
    }
}


private boolean canExecuteMovement(Bounds currentBounds, int xChange, int yChange)
{
    int projectedX = currentBounds.getX() + xChange;
    int projectedY = currentBounds.getY() + yChange;
    Bounds projectedBounds = new Bounds(projectedX, projectedY);
    // ^ Making an assumption about Bounds constructor but you get the idea

    for(int i = 0; i < platform.length; i ++)
    {
            if(projectedBounds.intersects(platform[i].getBounds())
            {
                    return false;
            }
    }

    return true;
}

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

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