当前位置: 首页 > 知识库问答 >
问题:

我该如何修复播放器碰撞,使它们不会经常卡住

魏旭
2023-03-14

我正在制作我的第一个2D游戏,当我向上移动并与瓷砖相撞时,它会停止,我仍然可以左右移动,但很难穿过门口。

下图显示了玩家被卡住的地方,他们不能向右或向下移动,也不能向上移动,但这是有意的

抱歉,如果我遗漏了一些重要的事情,这是我第一次发帖。

  • 编辑

为了澄清,我的碰撞框设置得比我的玩家小一点,这样玩家将与墙砖重叠一点,因此当试图穿过右侧的门口时,如果玩家碰撞框的顶部与墙砖碰撞框的底部发生碰撞,它确实会阻止玩家向上移动,但如果玩家试图继续向右移动,玩家将被阻止

玩家被卡在哪里的图像

  • 碰撞处理程序。java(处理所有冲突)
package game.handlers;

import game.GamePanel;
import game.entities.Entity;

import game.items.Item;
import game.items.objects.*;
import game.items.misc.*;

public class CollisionHandler
{
    GamePanel gp;

    public CollisionHandler(GamePanel gp)
    {
        this.gp = gp;
    }

    public void checkTile(Entity entity)
    {
        int entityLeftWorldX = entity.worldX + entity.collisionBox.x;
        int entityRightWorldX = entity.worldX + entity.collisionBox.x + entity.collisionBox.width;
        int entityTopWorldY = entity.worldY + entity.collisionBox.y;
        int entityBottemWorldY = entity.worldY + entity.collisionBox.y + entity.collisionBox.height;

        int entityLeftCol = entityLeftWorldX / gp.tileSize;
        int entityRightCol = entityRightWorldX / gp.tileSize;
        int entityTopRow = entityTopWorldY / gp.tileSize;
        int entityBottemRow = entityBottemWorldY / gp.tileSize;

        int tileNum1, tileNum2;
        
        switch(entity.direction)
        {
            case "up":
                entityTopRow = (entityTopWorldY - entity.speed) / gp.tileSize;
                tileNum1 = gp.tm.mapTileNum[entityLeftCol] [entityTopRow];
                tileNum2 = gp.tm.mapTileNum[entityRightCol] [entityBottemRow];

                if(gp.tm.tile[tileNum1].hasCollision || gp.tm.tile[tileNum2].hasCollision)
                {
                    entity.collisionOn = true;
                }

                break;
            case "down":
                entityBottemRow = (entityBottemWorldY + entity.speed) / gp.tileSize;
                tileNum1 = gp.tm.mapTileNum[entityLeftCol] [entityTopRow];
                tileNum2 = gp.tm.mapTileNum[entityRightCol] [entityBottemRow];

                if(gp.tm.tile[tileNum1].hasCollision || gp.tm.tile[tileNum2].hasCollision)
                {
                    entity.collisionOn = true;
                }

                break;
            case "left":
                entityLeftCol = (entityLeftWorldX - entity.speed) / gp.tileSize;
                tileNum1 = gp.tm.mapTileNum[entityLeftCol] [entityTopRow];
                tileNum2 = gp.tm.mapTileNum[entityRightCol] [entityBottemRow];

                if(gp.tm.tile[tileNum1].hasCollision || gp.tm.tile[tileNum2].hasCollision)
                {
                    entity.collisionOn = true;
                }

                break;
            case "right":
                entityRightCol = (entityRightWorldX + entity.speed) / gp.tileSize;
                tileNum1 = gp.tm.mapTileNum[entityLeftCol] [entityTopRow];
                tileNum2 = gp.tm.mapTileNum[entityRightCol] [entityBottemRow];

                if(gp.tm.tile[tileNum1].hasCollision || gp.tm.tile[tileNum2].hasCollision)
                {
                    entity.collisionOn = true;
                }
                
                break;
            default:
                break;
        }
    }

    public int checkItem(Entity entity, boolean player)
    {
        int index = 999;

        for(Item item: gp.items)
        {
            if(item != null)
            {
                entity.collisionBox.x = entity.worldX + entity.collisionBox.x;
                entity.collisionBox.y = entity.worldY + entity.collisionBox.y;

                item.collisionBox.x = item.worldX + item.collisionBox.x;
                item.collisionBox.y = item.worldY + item.collisionBox.y;

                switch(entity.direction)
                {
                    case "up":
                        entity.collisionBox.y -= entity.speed;
                        if(entity.collisionBox.intersects(item.collisionBox))
                        {
                            if(item.hasCollision)
                            {
                                entity.collisionOn = true;
                            }
                            if(player)
                            {
                                index = gp.items.indexOf(item);
                            }
                        
                        }
                        break;
                    case "down":
                        entity.collisionBox.y += entity.speed;
                        if(entity.collisionBox.intersects(item.collisionBox))
                        {
                           if(item.hasCollision)
                            {
                                entity.collisionOn = true;
                            }
                            if(player)
                            {
                                index = gp.items.indexOf(item);
                            }
                        }
                        break;
                    case "left":
                        entity.collisionBox.x -= entity.speed;
                        if(entity.collisionBox.intersects(item.collisionBox))
                        {
                            if(item.hasCollision)
                            {
                                entity.collisionOn = true;
                            }
                            if(player)
                            {
                                index = gp.items.indexOf(item);
                            }
                        }
                        break;
                    case "right":
                        entity.collisionBox.x += entity.speed;
                        if(entity.collisionBox.intersects(item.collisionBox))
                        {
                            if(item.hasCollision)
                            {
                                entity.collisionOn = true;
                            }
                            if(player)
                            {
                                index = gp.items.indexOf(item);
                            }
                        }
                        break;
                }
                /*switch(entity.direction)
                {
                    case "up":
                        entity.collisionBox.y -= entity.speed;
                        if(entity.collisionBox.intersects(item.collisionBox))
                        {
                            if(item instanceof SObject)
                            {
                                SObject object = (SObject)item;
                                object.interact(gp);

                                if(item.hasCollision)
                                {
                                    entity.collisionOn = true;
                                }
                                if(player)
                                {
                                    index = gp.items.indexOf(item);
                                }
                            }
                            else 
                            {
                                if(item.hasCollision)
                                {
                                    entity.collisionOn = true;
                                }
                                if(player)
                                {
                                    index = gp.items.indexOf(item);
                                }
                            }
                        
                        }
                        break;
                    case "down":
                        entity.collisionBox.y += entity.speed;
                        if(entity.collisionBox.intersects(item.collisionBox))
                        {
                            if(item instanceof SObject)
                            {
                                SObject object = (SObject)item;
                                object.interact(gp);

                                if(item.hasCollision)
                                {
                                    entity.collisionOn = true;
                                }
                                if(player)
                                {
                                    index = gp.items.indexOf(item);
                                }
                            }
                            else 
                            {
                                if(item.hasCollision)
                                {
                                    entity.collisionOn = true;
                                }
                                if(player)
                                {
                                    index = gp.items.indexOf(item);
                                }
                            }
                        }
                        break;
                    case "left":
                        entity.collisionBox.x -= entity.speed;
                        if(entity.collisionBox.intersects(item.collisionBox))
                        {
                            if(item instanceof SObject)
                            {
                                SObject object = (SObject)item;
                                object.interact(gp);

                                if(item.hasCollision)
                                {
                                    entity.collisionOn = true;
                                }
                                if(player)
                                {
                                    index = gp.items.indexOf(item);
                                }
                            }
                            else 
                            {
                                if(item.hasCollision)
                                {
                                    entity.collisionOn = true;
                                }
                                if(player)
                                {
                                    index = gp.items.indexOf(item);
                                }
                            }
                        }
                        break;
                    case "right":
                        entity.collisionBox.x += entity.speed;
                        if(entity.collisionBox.intersects(item.collisionBox))
                        {
                            if(item instanceof SObject)
                            {
                                SObject object = (SObject)item;
                                object.interact(gp);

                                if(item.hasCollision)
                                {
                                    entity.collisionOn = true;
                                }
                                if(player)
                                {
                                    index = gp.items.indexOf(item);
                                }
                            }
                            else 
                            {
                                if(item.hasCollision)
                                {
                                    entity.collisionOn = true;
                                }
                                if(player)
                                {
                                    index = gp.items.indexOf(item);
                                }
                            }
                        }
                        break;
                }*/
                entity.collisionBox.x = entity.defaultCollisionBoxX;
                entity.collisionBox.y = entity.defaultCollisionBoxY;

                item.collisionBox.x = item.defaultCollisionBoxX;
                item.collisionBox.y = item.defaultCollisionBoxY;
            }
        }

        return index;
    }

    public void interact(Entity entity, int index)
    {
        Item item = gp.items.get(index);
                
        if(item != null)
        {
            entity.collisionBox.x = entity.worldX + entity.collisionBox.x;
            entity.collisionBox.y = entity.worldY + entity.collisionBox.y;

            item.collisionBox.x = item.worldX + item.collisionBox.x;
            item.collisionBox.y = item.worldY + item.collisionBox.y;

            switch(entity.direction)
            {
                case "up":
                    entity.collisionBox.y -= entity.speed;
                    if(entity.collisionBox.intersects(item.collisionBox))
                    {
                        if(item.hasCollision)
                        {
                            entity.collisionOn = true;
                        }
                    
                    }
                    break;
                case "down":
                    entity.collisionBox.y += entity.speed;
                    if(entity.collisionBox.intersects(item.collisionBox))
                    {
                        if(item.hasCollision)
                        {
                            entity.collisionOn = true;
                        }
                    }
                    break;
                case "left":
                    entity.collisionBox.x -= entity.speed;
                    if(entity.collisionBox.intersects(item.collisionBox))
                    {
                        if(item.hasCollision)
                        {
                            entity.collisionOn = true;
                        }
                    }
                    break;
                case "right":
                    entity.collisionBox.x += entity.speed;
                    if(entity.collisionBox.intersects(item.collisionBox))
                    {
                        if(item.hasCollision)
                        {
                            entity.collisionOn = true;
                        }
                    }
                    break;
            }
            entity.collisionBox.x = entity.defaultCollisionBoxX;
            entity.collisionBox.y = entity.defaultCollisionBoxY;

            item.collisionBox.x = item.defaultCollisionBoxX;
            item.collisionBox.y = item.defaultCollisionBoxY;
        }
    }
}
  • 实体。java(i类扩展了玩家、敌人、NPC、exc等所有其他实体)
package game.entities;

import game.util.Inventory;
import game.items.Item;

import java.awt.image.*;
import java.awt.Rectangle;
import java.util.ArrayList;

public abstract class Entity
{
    public int health;
    public int maxHealth;

    public int worldX, worldY;
    public int speed;

    public BufferedImage up1, up2, down1, down2, left1, left2, right1, right2;
    public String direction;

    public int spriteCounter = 0;
    public int spriteNumber = 1;

    public Rectangle collisionBox;
    public int defaultCollisionBoxX, defaultCollisionBoxY;
    public boolean collisionOn = false;

    public Inventory inv = new Inventory(this);

    public Item equiped;

    public ArrayList<String> diialogues = new ArrayList<String>();

    public void heal(int amountToHeal)
    {
        health += amountToHeal;
        if(health > maxHealth)
        {
            health = maxHealth;
        }
    }

    public void damage(int amountToDamage)
    {
        health -= amountToDamage;
        if(health < 0)
        {
            health = 0;
        }
    }
}
  • 玩家。java(包含游戏玩家的类)
package game.entities;

import game.handlers.KeyHandler;
import game.items.Item;
import game.items.objects.SObject;
import game.GamePanel;

import java.awt.Graphics2D;
import java.awt.Color;
import java.awt.Rectangle;
import java.awt.image.*;
import java.io.*;
import javax.imageio.ImageIO;

public class Player extends Entity
{
    GamePanel gp;
    KeyHandler kh;

    public final int screenX;
    public final int screenY;

    public Player(GamePanel gp, KeyHandler kh)
    {
        this.gp = gp;
        this.kh = kh;

        screenX = gp.screenWidth/2 - (gp.tileSize/2);
        screenY = gp.screenHeight/2 - (gp.tileSize/2);

        collisionBox = new Rectangle(8, 16, 32, 32);

        defaultCollisionBoxX = collisionBox.x;
        defaultCollisionBoxY = collisionBox.y;

        worldX = gp.tileSize * 22;
        worldY = gp.tileSize * 46; //46
        
        speed = 4;

        direction = "down";

        health = 50;
        maxHealth = 100;

        getPlayerImage();
    }

    public void getPlayerImage()
    {
        try 
        {
            up1 = ImageIO.read(getClass().getResourceAsStream("/Resources/Entities/Player/boy_up_1.png"));
            up2 = ImageIO.read(getClass().getResourceAsStream("/Resources/Entities/Player/boy_up_2.png"));

            down1 = ImageIO.read(getClass().getResourceAsStream("/Resources/Entities/Player/boy_down_1.png"));
            down2 = ImageIO.read(getClass().getResourceAsStream("/Resources/Entities/Player/boy_down_2.png"));

            left1 = ImageIO.read(getClass().getResourceAsStream("/Resources/Entities/Player/boy_left_1.png"));
            left2 = ImageIO.read(getClass().getResourceAsStream("/Resources/Entities/Player/boy_left_2.png"));

            right1 = ImageIO.read(getClass().getResourceAsStream("/Resources/Entities/Player/boy_right_1.png"));
            right2 = ImageIO.read(getClass().getResourceAsStream("/Resources/Entities/Player/boy_right_2.png"));
        }
        catch(IOException e)
        {
            e.printStackTrace();
        }
    }

    public void interactObject(int index)
    {
        if(gp.kh.ePressed)
        {
            if(index != 999)
            {
                SObject object = (SObject)gp.items.get(index);
                object.interact(gp);
            }
        }
    }

    public void pickUpItem(int index)
    {
        if(index != 999)
        {
           if(gp.items.get(index) instanceof SObject)
           {
           }
           else 
           {
                //inv.items.add(gp.items.get(index));
                gp.items.set(index, null);
           }
        }
    }

    public void interactNPC(int index)
    {}

    public void update()
    {
        if(kh.downPressed || kh.upPressed || kh.leftPressed || kh.rightPressed)
        {
            if(kh.upPressed)
            {
                direction = "up";
            }

            if(kh.downPressed)
            {
                direction = "down";
            }

            if(kh.leftPressed)
            {
                direction = "left";
            }

            if(kh.rightPressed)
            {
                direction = "right";
            }

            collisionOn = false;
            gp.ch.checkTile(this);

            int itemIndex = gp.ch.checkItem(this, true);
            pickUpItem(itemIndex);

            if(!collisionOn)
            {
                switch(direction)
                {
                    case "up":
                        worldY -= speed;
                        break;
                    case "down":
                        worldY += speed;
                        break;
                    case "left":
                        worldX -= speed;
                        break;
                    case "right":
                        worldX += speed;
                        break;
                }
            }
            
            //int objectIndex = gp.ch.checkItem(this, true);
            //interactObject(objectIndex);

            gp.kh.ePressed = false;

            spriteCounter++;
            if(spriteCounter > 12)
            {
                if(spriteNumber == 1)
                {
                    spriteNumber = 2;
                }
                else if(spriteNumber == 2)
                {
                    spriteNumber = 1;
                }
                spriteCounter = 0;
            }
        }
    }

    public void draw(Graphics2D g2d)
    {
        BufferedImage image = null;

        switch(direction)
        {
            case "up":
                if(spriteNumber == 1)
                {
                    image = up1;
                }
                else if(spriteNumber == 2)
                {
                    image = up2;
                }
                break;
            case "down":
                if(spriteNumber == 1)
                {
                    image = down1;
                }
                else if(spriteNumber == 2)
                {
                    image = down2;
                }
                break;
            case "left":
                if(spriteNumber == 1)
                {
                    image = left1;
                }
                else if(spriteNumber == 2)
                {
                    image = left2;
                }
                break;
            case "right":
                if(spriteNumber == 1)
                {
                    image = right1;
                }
                else if(spriteNumber == 2)
                {
                    image = right2;
                }
                break;
            default:
                break;
        }

        int x = screenX;
        int y = screenY;

        if(screenX > worldX)
        {
            x = worldX;
        }

        if(screenY > worldY)
        {
            y = worldY;
        }

        int rightOffset = gp.screenWidth - gp.player.screenX;
        if(rightOffset > gp.worldWidth - gp.player.worldX)
        {
            x = gp.screenWidth - (gp.worldWidth - worldX);
        }

        int bottemOffset = gp.screenHeight - gp.player.screenY;
        if(bottemOffset > gp.worldHeight - gp.player.worldY)
        {
            y = gp.screenHeight -(gp.worldHeight - worldY);
        }

        g2d.drawImage(image, x, y, gp.tileSize, gp.tileSize, null);
    }
}
  • 钥匙手。java(处理我所有的密钥输入)
package game.handlers;

import game.GamePanel;

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

public class KeyHandler implements KeyListener
{
    GamePanel gp;

    public boolean upPressed, leftPressed, downPressed, rightPressed;
    public boolean ePressed, enterPressed;

    private boolean u, u2, d, d2, l, r, l2, r2;

    public KeyHandler(GamePanel gp)
    {
        this.gp = gp;
    }

    @Override
    public void keyTyped(KeyEvent e)
    {}

    @Override
    public void keyPressed(KeyEvent e)
    {
        int input = e.getKeyCode();

        if(gp.gameState == gp.playState)
        {
            if(input == KeyEvent.VK_W)
            {
                upPressed = true;
            }

            if(input == KeyEvent.VK_A)
            {
                leftPressed = true;
            }

            if(input == KeyEvent.VK_S)
            {
                downPressed = true;
            }

            if(input == KeyEvent.VK_D)
            {
                rightPressed = true;
            }

            //interact key
            if(input == KeyEvent.VK_E)
            {
                ePressed = true;
            }

            //Dev mode
            if(input == KeyEvent.VK_UP)
            {
                if(!u)
                {
                    u = true;
                }
                else if(u)
                {
                    u2 = true;
                }

                if(u && u2)
                {
                    if(!gp.devMode)
                    {
                        gp.devMode = true;
                    }
                    else if(gp.devMode)
                    {
                        gp.devMode = false;
                    }
                }
            }

            if(gp.devMode)
            {
                if(input == KeyEvent.VK_T)
                {
                    gp.player.heal(5);
                }

                if(input == KeyEvent.VK_Y)
                {
                    gp.player.damage(5);
                }
            }
        }

        if(gp.gameState == gp.playState || gp.gameState == gp.pauseState)
        {
            //Toggle Pause Menu
            if(input == KeyEvent.VK_P)
            {
                if(gp.gameState == gp.playState)
                {
                    gp.gameState = gp.pauseState;
                }
                else if(gp.gameState == gp.pauseState)
                {
                    gp.gameState = gp.playState;
                }
            }
        }

        if(gp.gameState == gp.textState)
        {
            if(input == KeyEvent.VK_ENTER)
            {
                enterPressed = true;
            }
        }
    }

    @Override
    public void keyReleased(KeyEvent e)
    {
        int input = e.getKeyCode();

        if(input == KeyEvent.VK_W)
        {
            upPressed = false;
        }

        if(input == KeyEvent.VK_A)
        {
            leftPressed = false;
        }

        if(input == KeyEvent.VK_S)
        {
            downPressed = false;
        }

        if(input == KeyEvent.VK_D)
        {
            rightPressed = false;
        }
    }
}

我将非常感谢任何可以提供的帮助以及任何建议

共有1个答案

陶博赡
2023-03-14

回答你关于重构的问题:在很多地方,你的代码可以变得更干净、更高效。例如,考虑KeyHandler中的这一部分。爪哇:

if(!u)
{
   u = true;
}
else if(u)
{
   u2 = true;
}

if(u && u2)
{
   if(!gp.devMode)
   {
       gp.devMode = true;
   }
   else if(gp.devMode)
   {
       gp.devMode = false;
   }
}

看看第一个if语句。如果u为false,则输入第一个分支并将其设置为true。否则u为true,则输入第二个分支。在这第二个分支中,您有一个测试if(u)。但是只有当u为true时,您才能输入这个分支!这意味着您不需要再次检查它,它可以简化为

if (!u) {
   u = true;
} else {
   u2 = true;
}

现在,您可以看到在执行此if语句后,u的值将始终为真(因为它要么从一开始就为真,要么在第一个分支中设置为真)。因此,它可以更加简化:

java prettyprint-override">if (u) {
   u2 = true;
}
u = true;

之后是下一个if语句。条件是if(u

if(!gp.devMode)
{
    gp.devMode = true;
}
else if(gp.devMode)
{
    gp.devMode = false;
}

在这里您再次使用u变量执行与之前相同的过度测试:不需要第二个if(gp.devMode)检查,因为为了进入这个分支gp.devMode必须已经为真。此if-语句的全部含义是切换gp.devMode的值:如果为真,则将其设置为false,反之亦然。您可以通过一个简单的赋值来实现这一点:

gp.devMode = !gp.devMode;

因此,第二个if语句可以简化为

if (u2) {
   gp.devMode =! gp.devMode;
}

我们开始的整个代码块被简化为

if (u) {
  u2 = true;
}
u = true;
if (u2) {
  gp.devMode = !gp.devMode;
}

这只是代码的简化,同时保持相同的逻辑。在许多地方,逻辑也可以简化或更改。

而且,现在的代码很容易出现简单的打字错误。例如,要指定运动方向,请使用字符串。如果在其中一个地方你不小心输入了“rigth”而不是“right”,会发生什么?程序将编译并运行,但无法正常工作,并且很难发现错误。在这种情况下,更好的解决方案是使用枚举。所以,创建一个新的文件方向。爪哇:

public enum Direction {
  UP,
  DOWN,
  LEFT,
  RIGHT
}

然后在实体类中替换声明

public String direction;

具有

public Direction direction;

当需要使用它时,可以用相应的枚举值替换字符串,例如:

switch(direction) {
    case Direction.UP:
            worldY -= speed;
            break;
    case Direction.DOWN:
            worldY += speed;
            break;
    case Direction.LEFT:
            worldX -= speed;
            break;
    case Direction.RIGHT:
            worldX += speed;
            break;
}

这样效率更高,也不容易出错。如果你打错并写下方向。RIGTH,则代码将无法编译。如果您忘记在switch语句中指定所有的大小写,编译器现在也可以警告您。

还有许多其他地方可以改进(例如,您始终破坏封装),但让我们回到您关于碰撞的主要问题。从您提供的信息中很难说,但我认为您的播放器的碰撞框看起来有点像下图中的红色矩形:

现在,假设玩家在门的左侧和上方,玩家想要向右移动:

在碰撞检测代码中,您有以下内容:

case "right":
       entityRightCol = (entityRightWorldX + entity.speed) / gp.tileSize;
       tileNum1 = gp.tm.mapTileNum[entityLeftCol] [entityTopRow];
       tileNum2 = gp.tm.mapTileNum[entityRightCol] [entityBottemRow];

       if(gp.tm.tile[tileNum1].hasCollision || gp.tm.tile[tileNum2].hasCollision)
       {
          entity.collisionOn = true;
       }
       break;

它说,你计算出玩家右侧偏右的位置,然后检查左上方和右下方的瓷砖,即前一张图片上绿色显示的瓷砖。你现在看到问题了吗?你应该检查右顶部和右底部的瓷砖。但是,由于您的错误,没有检测到右上角与墙的碰撞,玩家可以在墙内进一步移动。

现在你会遇到这样的情况:

假设您现在按下向下键。检查如下:

case "down":
     entityBottemRow = (entityBottemWorldY + entity.speed) / gp.tileSize;
     tileNum1 = gp.tm.mapTileNum[entityLeftCol] [entityTopRow];
     tileNum2 = gp.tm.mapTileNum[entityRightCol] [entityBottemRow];

     if(gp.tm.tile[tileNum1].hasCollision || gp.tm.tile[tileNum2].hasCollision)
     {
         entity.collisionOn = true;
     }
     break;

再次检查左上角和右下角。右下角是自由的,但左上角卡在墙上,你不能移动。除向左移动外,其他所有方向也是如此。

为了解决这一问题,您需要在每种情况下检查两块瓷砖,它们位于所需移动的方向:

case UP:    check left-top and right-top;
case DOWN:  check left-bottom and right-bottom;
case LEFT:  check left-top and left-bottom;
case RIGHT: check right-top and right-bottom;

 类似资料:
  • 当我一次又一次点击播放按钮时,它会同时播放多次。我想停止多重播放。这是代码: 媒体播放器和按钮的对象 按钮单击事件监听器以播放音频 按钮单击事件侦听器以停止音频 任何帮助都将不胜感激。谢谢

  • 我正在我的游戏中实现碰撞检测,并有一点麻烦,理解如何计算矢量,以固定我的形状重叠碰撞。 举个例子,我有两个方块。和。对于这两者,我都知道它们的、、和。但是是移动的,所以他有一个速度和一个速度。假设我每秒更新一次游戏。我已经说明了下面的情况。 现在,我需要一个公式来得到矢量来固定重叠。如果我将这个向量应用到红色方块(),它们就不会再重叠了。这就是我想要达到的目标。 谁能帮我算出计算向量的公式吗? 如

  • 当我尝试播放我的音乐时,Discord机器人不会播放音乐。它使用ytdl核心和ffmpeg。我的代码是: 每当我尝试播放歌曲时,都会发生以下错误: (节点:5180)未处理的PromisejectionWarning:错误:找不到FFmpeg/avconv!在功能上。getInfo(C:\Users\picar\Desktop\DiscordMusicBot\node\u modules\pris

  • 我正在尝试编程一个简单的2D平台,我想让玩家浏览一些平台。不幸的是,我的玩家无缘无故地在某些平台上绊倒: 这显然不是我想要的。我唯一能想象的是,由于某种原因,这些盒子的高度不一样。。。但如何解决这个问题呢?以下是我的一些代码: createPlatform。。。 Runner.java-act()

  • 我已经尝试解决了平滑的玩家-墙壁碰撞的问题,这样玩家可以沿着墙壁滑动。 我尝试了以下内容: 但是如果玩家碰到了墙,他不会滑动...他只是停下来了。(我对W,A,S,D也是分开做的。) 只有当我将玩家位置设置回他正在触摸的墙壁位置时,它才有效。如下: 但是它不起作用,因为对于与另一面墙相连的墙,玩家会接触更多的边,玩家会跳到角落...所以它只适用于一面墙... 我的问题是:如何以另一种方式使玩家与墙

  • 获取碰撞器组件 Cocos Creator 3D 目前支持两种语言进行开发,分别为JavaScript和TypeScript。 注:TypeScript具有良好的语法分析和类型提示,推荐使用。 以获取BoxCollider为例,在JavaScript中获取Collider组件: this.getComponent('BoxCollider') this.getComponent(BoxCollid