我应该如何在这个 2d Java 游戏中实现跳跃/重力/下落

2024-03-02

所以这是我的Player类(我想在空格键上跳转的对象),我只是不知道从哪里开始,我可以在互联网上阅读与我相关的任何好的资源吗?任何帮助都很棒,谢谢。

package com.zetcode;
import java.awt.Color;
import java.awt.Graphics;

public class Player extends Creature {

    private boolean jumping = false;
    private Creature creature;

    public Player(Handler handler, float x, float y) {
        super(handler, x, y, Creature.PLAYER_WIDTH, Creature.PLAYER_HEIGHT);

        bounds.x = 16;
        bounds.y = 31;
        bounds.width = 40;
        bounds.height = 58;
    }

    @Override
    public void tick() {
        getInput();
        move();
        handler.getGameCamera().centerOnEntity(this);
    }

    private void getInput(){
        xMove = 0;
        yMove = 3;
        gravity = 2;

        if(handler.getKeyManager().jump)
            yMove = -speed;
        if(handler.getKeyManager().down)
            yMove = speed;
        if(handler.getKeyManager().left)
            xMove = -speed;
        if(handler.getKeyManager().right)
            xMove = speed;
    }

    @Override
    public void render(Graphics g) {
        g.drawImage(Assets.player, (int) (x -     handler.getGameCamera().getxOffset()), (int) (y -   handler.getGameCamera().getyOffset()), width, height, null);
    }
}

这是我的KeyManager class:

package com.zetcode;

import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

public class KeyManager implements KeyListener{

    private boolean[] keys;
    public boolean up, down, left, right, jump;

    public KeyManager(){
        keys = new boolean[256];
    }

    public void tick(){
        down = keys[KeyEvent.VK_S];
        left = keys[KeyEvent.VK_A];
        right = keys[KeyEvent.VK_D];
        jump = keys[KeyEvent.VK_SPACE];
    }

    @Override
    public void keyPressed(KeyEvent e) {
        keys[e.getKeyCode()] = true;
        System.out.println("A Key was pressed");
    }

    @Override
    public void keyReleased(KeyEvent e) {
        keys[e.getKeyCode()] = false;
    }

    @Override
    public void keyTyped(KeyEvent e) {

    }
}

我一直在努力实现一种让我的角色跳跃的方法,目前玩家按下空格键可以沿 Y 轴向上移动,但我可以按住按键并无限跳跃。

我会添加我的Creature有碰撞检测的类:

package com.zetcode;

public abstract class Creature extends Entity {

    public static final int DEFAULT_HEALTH = 10;
    public static final float DEFAULT_SPEED = 3.0f;
    public static final int DEFAULT_CREATURE_WIDTH = 64,
            DEFAULT_CREATURE_HEIGHT = 64;
    public static final int PLAYER_HEIGHT = 90, PLAYER_WIDTH = 64;

    protected int health;
    protected float speed;
    protected float xMove, yMove;
    protected float gravity;

    public boolean falling = true;
    private boolean jumping = false;

    public Creature(Handler handler, float x, float y, int width, int height) {
        super(handler, x, y, width, height);
        health = DEFAULT_HEALTH;
        speed = DEFAULT_SPEED;
        xMove = 0;
        yMove = 0;
        gravity = 0;
    }

    //collision detection

    public void move(){
        moveX();
        moveY();
    }

    public void moveX(){
        if(xMove > 0){//move right
            int tx = (int) (x + xMove + bounds.x + bounds.width) / Tile.TILE_WIDTH;

            if(!collisionWithTile(tx, (int) (y + bounds.y) / Tile.TILE_HEIGHT) && //check top right corner of hitbox
                    !collisionWithTile(tx, (int) (y + bounds.y + bounds.height) / Tile.TILE_HEIGHT)){ //check bottom right corner of hitbox
                x += xMove;
            }else{
                x = tx * Tile.TILE_WIDTH - bounds.x - bounds.width - 1;
            }

        }else if(xMove < 0){//move left
            int tx = (int) (x + xMove + bounds.x) / Tile.TILE_WIDTH;

            if(!collisionWithTile(tx, (int) (y + bounds.y) / Tile.TILE_HEIGHT) && //check top left corner of hitbox
                    !collisionWithTile(tx, (int) (y + bounds.y + bounds.height) / Tile.TILE_HEIGHT)){ //check bottom left corner of hitbox
                x += xMove;
            }else{
                x = tx * Tile.TILE_WIDTH + Tile.TILE_WIDTH - bounds.x;
            }
        }
    }

    public void moveY(){
        if(yMove < 0){//up
            int ty = (int) (y+ yMove + bounds.y) / Tile.TILE_HEIGHT;

            if(!collisionWithTile((int) (x + bounds.x) / Tile.TILE_WIDTH, ty) &&
                    !collisionWithTile((int) (x + bounds.x + bounds.width) / Tile.TILE_WIDTH,ty)){
                y += yMove;
            }else{
                y = ty * Tile.TILE_HEIGHT + Tile.TILE_HEIGHT - bounds.y;
            }

        }else if(yMove > 0){//down
            int ty = (int) (y+ yMove + bounds.y + bounds.getHeight()) /      Tile.TILE_HEIGHT;

            if(!collisionWithTile((int) (x + bounds.x) / Tile.TILE_WIDTH,ty) &&
                    !collisionWithTile((int) (x + bounds.x + bounds.width) /   Tile.TILE_WIDTH,ty)){
                y += yMove;
            }else{
                y = ty * Tile.TILE_HEIGHT - bounds.y - bounds.height -1;
            }
        }
    }

    protected boolean collisionWithTile(int x, int y){
        return handler.getWorld().getTile(x, y).isSolid();
    }

    //getters and setters

    public float getxMove() {
        return xMove;
    }

    public void setxMove(float xMove) {
        this.xMove = xMove;
    }

    public float getyMove() {
        return yMove;
    }

    public void setyMove(float yMove) {
        this.yMove = yMove;
    }

    public int getHealth() {
        return health;
    }

    public void setHealth(int health) {
        this.health = health;
    }

    public float getSpeed() {
        return speed;
    }

    public void setSpeed(float speed) {
        this.speed = speed;
    }
}

你想做的,就是落实speed, 加速度 and gravity对于场景中的对象。速度是一个二维向量,它告诉你某物移动的速度有多快,而加速度告诉你速度增加多少.

所有对象都应该有一个update()方法,定期调用。它将把物体的速度应用到它的位置(这就是速度和位置的关系),当你想要加速一个物体时,你基本上只会增加它的速度。在里面update()我们还应用重力(以负 Y 加速度的形式)

您还可以利用摩擦力。摩擦力确保您的物体在向某个方向移动时会减慢速度。

在这个简单的模拟中,随着值接近,摩擦力会变弱1。这意味着在FRICTION==1你没有摩擦力并且在FRICTION==0你的物体将立即停止。

public class PhysicsObject {
    public static final double FRICTION = 0.99;
    public static final double GRAVITY = 0.01;
    private double posX;
    private double posY;
    private double speedX = 0;
    private double speedY = 0;

    public PhysicsObject(double posX, double posY) {
        this.posX = posX;
        this.posY = posY;
    }

    public void accelerate(double accelerationX, double accelerationY) {
        speedX += accelerationX;
        speedY += accelerationY;
    }

    public void move(double xDelta, double yDelta) {
        posX += xDelta;
        posY += yDelta;
        // do collision detection here. upon collision, set speedX/speedY to zero..!
    }

    public void update() {
        move(speedX, speedY);
        speedX *= FRICTION;
        speedY *= FRICTION;
        accelerate(0, -GRAVITY); // gravity accelerates the object downwards each tick
    }

    public double getPosX() {
        return posX;
    }

    public double getPosY() {
        return posY;
    }
}

您还可以使用update()处理碰撞检测(应将速度设置为零),敌人可以执行他们的人工智能逻辑。

你上课Player可以延长这个PhysicsObject并有方法jump(), runLeft() and runRight(),可能如下所示:

public class Player extends PhysicsObject{
    public static final double JUMP_STRENGTH = 5;
    public static final double SPEED = 1;
    public void jump() {
        accelerate(0, JUMP_STRENGTH); // change 5 for some constant or variable indicating the "strength" of the jump
    }

    public void runRight() {
        move(SPEED, 0);
    }

    public void runLeft() {
        move(-SPEED, 0);
    }
}

碰撞检测本身就是一件大事,这里无法涵盖太多,但是这个视频 https://www.youtube.com/watch?v=NZHzgXFKfuY描述得很好。去看看吧!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

我应该如何在这个 2d Java 游戏中实现跳跃/重力/下落 的相关文章

随机推荐

  • 如何在企业架构师的下拉列表中添加多个标记值?

    我正在使用企业架构师 我希望在下拉列表中显示多个值作为标记值 我只能为标记值赋予一个值 但我不知道如何为一系列选择执行此操作 我在 sparx 系统的用户指南中找不到帮助 也许我没有找到它 有什么帮助吗 谢谢 创建下拉标记值列表企业架构师
  • Xamarin.iOS 在应用程序未关闭时处理推送通知

    如果应用程序在后台使用该方法 我设法处理推送通知didReceiveRemoteNotification 如果应用程序位于前台且未关闭 是否有办法处理推送通知 谢谢 你实施了吗用户通知 https developer apple com d
  • iTunesConnect 要求我提交“年终自我资格报告”

    当我尝试提交我的应用程序进行测试时 出现了此问题 如果您使用 ATS 或调用 HTTPS 请注意 您需要提交年终自我分类报告 给美国政府 答案是肯定的 我确实会调用 https 来与我的 API 对话 我具体应该怎么做才能满足这个要求呢 什
  • 在 Django 中运行 Discord 机器人

    我想要一个访问 Django 数据库的不和谐机器人 一个明显的解决方案是有两个单独的脚本 我想知道是否有办法使不和谐机器人作为应用程序或其他东西成为 Django 的一部分 您可以在单独的线程中运行不和谐机器人 并且还可以相互设置属性 同样
  • 如何将已修补的 GNU readline 库正确链接到所有现有程序?

    我最初的问题是 我想要一种方法来区分在 vi 模式下使用 bash 时是处于 vi 命令模式还是 vi 插入模式 据我了解 从 GNU readline 7 0 开始 有一种方法可以在命令提示符中设置指示器 然而 我想要的是改变光标的形状
  • 有没有办法阻止 SqlPackage.exe 在部署脚本中设置默认文件组?

    我们正在使用 Sql Server 数据库项目通过 SqlPackage exe 从 DacPac 创建部署脚本 我们在不同的环境中设置了不同的 SQL Server 文件组 部署时 我们排除文件组 因为我们希望在默认文件组中创建对象 在数
  • 使用 Numba 处理 pandas DataFrame 时间序列的有效方法

    我有一个包含 1 500 000 行的 DataFrame 这是我从 QuantQuote com 购买的一分钟级别的股市数据 开盘价 最高价 最低价 收盘价 交易量 我正在尝试对股票市场交易策略进行一些自制的回测 直接使用 python
  • Json和Xml序列化,哪个性能更好?

    我必须在文件中存储一些配置信息 在 C 代码中 配置数据按类表示 在文件中我将以 json 或 xml 格式保存此类 那么 序列化json和xml哪个性能最好呢 好吧 我没有猜测 而是有了答案 这是测试程序 class Program st
  • 适合初学者的 SAML 简单示例

    我是 SAML v2 0 技术的初学者 我获得了理论知识 但我在 Google 上没有找到任何示例 任何人都可以为我提供简单的 SAML for v2 0 的分步示例 到目前为止我已经完成了理论部分 即它支持单点登录 and我也了解服务提供
  • 如何让 Wicket 7 与 Java 8 中的 java.time 配合使用?

    我有很多 bean 并且都使用 LocalDate 和 LocalDateTime Wicket 中的 DateTextField 和所有其他小部件 如 DatePicker 仅适用于 java util Date 有什么办法可以injec
  • 从字符串列表中找到与给定字符串匹配的最佳子集

    我有一根绳子 s mouse 和一个字符串列表 sub strings m o se e 我需要找出与 s 匹配的列表的 sub strings 的最佳和最短匹配子集是什么 做这个的最好方式是什么 理想的结果是 m o se 因为它们一起拼
  • 使用javascript检查用户是否是第一次访问

    我正在尝试构建一个系统 如果用户第一次登陆某个页面 则不会发生任何事情 但如果同一用户再次访问 则该页面不应加载 而是应该转到不同的 URL function session if document cookie indexOf visit
  • 从文本文件中删除前 N 个字节

    是否有任何函数调用或简单的方法可以从 golang 中的文本文件中删除前 N 个字节 假设该文件被各种 go 例程有争议地附加 同时我想删除文件的前 N 个字节 你需要做f Seek要跳过第一个字节并进行常规读取 请参见示例 package
  • 如何获得 mallet 中某个主题的概率分布?

    使用木槌 我可以获得特定数量的主题及其单词 如何确保主题词符合概率分布 即总和为一 例如 如果我按如下方式运行它 如何使用 mallet 给出的输出来确保主题 0 的主题词的概率加起来为 1 mallet train topics inpu
  • 在Java中使用线程同时执行多个方法[关闭]

    很难说出这里问的是什么 这个问题是含糊的 模糊的 不完整的 过于宽泛的或修辞性的 无法以目前的形式得到合理的回答 如需帮助澄清此问题以便重新打开 访问帮助中心 help reopen questions 就我而言 我有三个不同类别的三种方法
  • 在hibernate标准中使用mysql“按情况排序”

    我正在使用 Hibernate 4 3 1 Final Mysql 5 5 并且我想在某些连接实体上使用 按案例排序 的顺序逻辑 我希望实现的目标的纯 sql 表示如下 select adv id adv published date fr
  • 如何使用 jQuery 从 检索值?

    我必须隐藏输入字段 例如
  • 通过 sql 表中的 100,000 条记录进行通配符搜索的最佳优化技术是什么

    我正在开发 ASP NET MVC 应用程序 该应用程序有 200 个用户使用 这些 用户不断地 每 5 分钟 从 100 000 个项目的列表中搜索一个项目 该列表每个月都会增加 1 2 此 100 000 个项目的列表存储在 SQL S
  • ASP.NET Core AuthorizationHandler 未被调用

    我正在尝试添加一些基于自定义角色的authorisation 但我无法 将启动配置为调用我的AuthorizationHandler 我在GitHub上找到了一些相关信息 here https github com dotnet aspne
  • 我应该如何在这个 2d Java 游戏中实现跳跃/重力/下落

    所以这是我的Player类 我想在空格键上跳转的对象 我只是不知道从哪里开始 我可以在互联网上阅读与我相关的任何好的资源吗 任何帮助都很棒 谢谢 package com zetcode import java awt Color impor