内容来自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一下或直接下载获得完整项目