内容来自RyiSnow视频讲解
这一节讲的是Inventory背包,类似RPG游戏中人物角色放置装备、药品、武器、宝石等物品的一个若干行若干列的表格窗口。
可以显示装备物品,并选择它们。
前言
作者说这一节可能是第二部分里面爬起来最高的山峰。
效果

 最后还有一个中文效果,可以看下面。
实现
创建子窗口
创建一个子窗口,宽度6 tileSize,高度5 tileSize。

 内容容量为20,4行5列。预计是下面这个图片所示。
 
绘制光标格子
public class UI {
	public void drawInventory() {
	...
		// CURSOR
		int cursorX = slotXstart + (gp.tileSize * slotCol);
		int cursorY = slotYstart + (gp.tileSize * slotRow);
		int cursorWidth = gp.tileSize;
		int cursorHeight = gp.tileSize;
		// DRAW CURSOR
		g2.setColor(Color.white);
		g2.setStroke(new BasicStroke(3));
		g2.drawRoundRect(cursorX, cursorY, cursorWidth, cursorHeight, 10 ,10);
	}
}

 格子的边框线条有点粗,修改一下
 
// CURSOR
int cursorX = slotXstart + (gp.tileSize * slotCol);
int cursorY = slotYstart + (gp.tileSize * slotRow);
int cursorWidth = gp.tileSize;
int cursorHeight = gp.tileSize;
// DRAW CURSOR
g2.setColor(Color.white);
g2.setStroke(new BasicStroke(3));
g2.drawRoundRect(cursorX, cursorY, cursorWidth, cursorHeight, 10 ,10);
移动光标格子
修改KeyHandler实现。作者增加了一个移动光标格子音效。
public class KeyHandler {
public void characterState(int code) {
    if (code == KeyEvent.VK_C) {
        gp.gameState = gp.playState;
    }
    if (code == KeyEvent.VK_W) {
        gp.ui.slotRow--;
        gp.playSE(9);
    }
    if (code == KeyEvent.VK_A) {
        gp.ui.slotCol--;
        gp.playSE(9);
    }
    if (code == KeyEvent.VK_S) {
        gp.ui.slotRow++;
        gp.playSE(9);
    }
    if (code == KeyEvent.VK_D) {
        gp.ui.slotCol++;
        gp.playSE(9);
    }
}
}
关于音效播放,作者所用的方法经常出现一个
异常,已经不止一次了,这个问题后续必须要解决。即使不出异常,音效时有时无,有时候播放不出来,体验很差。
javax.sound.sampled.LineUnavailableException: line with format PCM_SIGNED 48000.0 Hz, 16 bit, stereo, 4 bytes/frame, little-endian not supported.
	at com.sun.media.sound.DirectAudioDevice$DirectDL.implOpen(DirectAudioDevice.java:513)
	at com.sun.media.sound.DirectAudioDevice$DirectClip.implOpen(DirectAudioDevice.java:1322)
	at com.sun.media.sound.AbstractDataLine.open(AbstractDataLine.java:120)
	at com.sun.media.sound.DirectAudioDevice$DirectClip.open(DirectAudioDevice.java:1091)
	at com.sun.media.sound.DirectAudioDevice$DirectClip.open(DirectAudioDevice.java:1193)
	at main.Sound.setFile(Sound.java:30)
	at main.GamePanel.playSE(GamePanel.java:263)
	at main.KeyHandler.characterState(KeyHandler.java:174)
	........

增加限制防止光标跑到子窗口外面
public void characterState(int code) {
    if (code == KeyEvent.VK_C) {
        gp.gameState = gp.playState;
    }
    if (code == KeyEvent.VK_W) {
        if (gp.ui.slotRow != 0) {
            gp.ui.slotRow--;
            gp.playSE(9);
        }
    }
    if (code == KeyEvent.VK_A) {
        if (gp.ui.slotCol != 0) {
            gp.ui.slotCol--;
            gp.playSE(9);
        }
    }
    if (code == KeyEvent.VK_S) {
        if (gp.ui.slotRow != 3) {//row:0,1,2,3
            gp.ui.slotRow++;
            gp.playSE(9);
        }
    }
    if (code == KeyEvent.VK_D) {
        if (gp.ui.slotCol!=4) {//col:0,1,2,3,4
            gp.ui.slotCol++;
            gp.playSE(9);
        }
    }
}
显示玩家的物品

public void drawInventory() {
    // FRAME
    int frameX = gp.tileSize * 9;
    int frameY = gp.tileSize;
    int frameWidth = gp.tileSize * 6;
    int frameHeight = gp.tileSize * 5;
    drawSubWindow(frameX, frameY, frameWidth, frameHeight);
    // SLOT
    final int slotXstart = frameX + 20;
    final int slotYstart = frameY + 20;
    int slotX = slotXstart;
    int slotY = slotYstart;
    // DRAW PLAYER'S ITEMS
    for (int i = 0; i < gp.player.inventory.size(); i++) {
        // down1 is default image
        g2.drawImage(gp.player.inventory.get(i).down1, slotX, slotY, null);
        slotX += gp.tileSize;
        if (i == 4 || i == 9 || i == 14) {
            slotX = slotXstart;
            slotY += gp.tileSize;
        }
    }
    ......
右侧空隙过大,调整一下。具体可参考项目代码。
 
增加网格线
这个作者没有,自己增加做个练习,显示效果不太好。
 
显示光标所在物品的描述信息
创建一个描述子窗口,位于物品窗口下方,显示装备物品的名称和描述信息。
 
public class UI {
	public void drawInventory() {
	......
		// DESCRIPTION FRAME
        int dFrameX = frameX;
        int dFrameY = frameY + frameHeight;
        int dFrameWidth = frameWidth;
        int dFrameHeight = gp.tileSize * 3;
        drawSubWindow(dFrameX, dFrameY, dFrameWidth, dFrameHeight);
        // DRAW DESCRIPTION TEXT
        int textX = dFrameX + 20;
        int textY = dFrameY + gp.tileSize;
        g2.setFont(arial_40);
        g2.setFont(g2.getFont().deriveFont(28F));
        int itemIndex = getItemIndexOnSlot();
        if (itemIndex < gp.player.inventory.size()) {
            String[] descArr = gp.player.inventory.get(itemIndex).description.split("\n");
            for (String line : descArr) {
                g2.drawString(line, textX, textY);
                textY += 32;
            }
        }
    }
}
移动光标,描述信息相应改变。用中文试了一下。效果还行。
 
代码
参考第6篇文章最后gitee仓库链接,可以使用git clone命令clone一下或直接下载获得完整项目



















