求助:在Slick2D的BasicGameState中实现用户名输入的高效方案
我之前在Slick2D开发游戏时也碰到过这个文本输入的坑,给你两个实用的解决方案:
方案1:修复内置TextField在BasicGameState中的问题
很多时候内置TextField不工作,只是因为我们漏了关键的初始化或生命周期调用步骤。试试按照下面的流程来:
- 在
BasicGameState的init方法中正确初始化TextField,记得传入GameContainer的Input实例; - 在
update方法中调用TextField的update方法,让它处理输入逻辑; - 在
render方法中调用TextField的render方法,渲染文本框; - 确保给TextField设置焦点,否则它不会响应输入。
示例代码:
import org.newdawn.slick.*; import org.newdawn.slick.state.BasicGameState; import org.newdawn.slick.state.StateBasedGame; public class UsernameInputState extends BasicGameState { private TextField usernameField; private int stateId; public UsernameInputState(int stateId) { this.stateId = stateId; } @Override public void init(GameContainer container, StateBasedGame game) throws SlickException { // 初始化TextField:参数依次是字体、输入实例、x坐标、y坐标、宽度、高度 usernameField = new TextField(container.getGraphics().getFont(), container.getInput(), 150, 200, 250, 35); usernameField.setBorderColor(Color.LIGHT_GRAY); usernameField.setTextColor(Color.WHITE); usernameField.setFocus(true); // 默认获取输入焦点 usernameField.setMaxLength(15); // 限制用户名最大长度 } @Override public void update(GameContainer container, StateBasedGame game, int delta) throws SlickException { usernameField.update(delta); // 必须调用,让TextField处理输入状态更新 } @Override public void render(GameContainer container, StateBasedGame game, Graphics g) throws SlickException { g.drawString("请输入用户名:", 100, 210); usernameField.render(container, g); // 渲染文本框 } @Override public int getID() { return stateId; } }
如果还是有问题,可以检查是否在StateBasedGame中正确切换到了这个状态,或者有没有其他Input监听器抢占了输入事件。
方案2:自定义高效文本输入组件
如果内置TextField实在不满足需求,我们可以自己封装一个,利用Slick2D的Input.getInputString()方法来批量处理输入字符,不用逐个检测按键,效率很高:
首先创建自定义文本框类:
import org.newdawn.slick.*; public class CustomTextField { private String inputText = ""; private final int x, y, width, height; private final Font font; private boolean isFocused = false; private Color textColor = Color.WHITE; private Color borderColor = Color.GRAY; public CustomTextField(Font font, int x, int y, int width, int height) { this.font = font; this.x = x; this.y = y; this.width = width; this.height = height; } public void update(Input input) { if (!isFocused) return; // 处理退格键 if (input.isKeyPressed(Input.KEY_BACK) && !inputText.isEmpty()) { inputText = inputText.substring(0, inputText.length() - 1); } // 处理回车键(可选:提交输入) if (input.isKeyPressed(Input.KEY_ENTER)) { isFocused = false; // 这里可以添加提交逻辑,比如把用户名传给游戏主逻辑 System.out.println("用户名:" + inputText); } // 处理所有可打印字符(自动处理大小写、符号,不用逐个检测按键) String newInput = input.getInputString(); if (!newInput.isEmpty()) { // 检查文本长度是否超出文本框宽度 if (font.getWidth(inputText + newInput) <= width - 10) { inputText += newInput; } } } public void render(Graphics g) { // 绘制边框 g.setColor(borderColor); g.drawRect(x, y, width, height); // 绘制输入文本 g.setColor(textColor); g.setFont(font); // 垂直居中文本 int textY = y + (height - font.getLineHeight()) / 2; g.drawString(inputText, x + 5, textY); // 绘制闪烁光标(聚焦时显示) if (isFocused) { long currentTime = System.currentTimeMillis() % 1000; if (currentTime < 500) { int cursorX = x + 5 + font.getWidth(inputText); g.drawLine(cursorX, y + 5, cursorX, y + height - 5); } } } // 辅助方法:设置/获取焦点 public void setFocused(boolean focused) { this.isFocused = focused; } public boolean isFocused() { return isFocused; } // 获取输入的文本 public String getInputText() { return inputText; } }
然后在你的BasicGameState中使用这个自定义组件:
import org.newdawn.slick.*; import org.newdawn.slick.state.BasicGameState; import org.newdawn.slick.state.StateBasedGame; public class CustomInputState extends BasicGameState { private CustomTextField usernameInput; private int stateId; public CustomInputState(int stateId) { this.stateId = stateId; } @Override public void init(GameContainer container, StateBasedGame game) throws SlickException { usernameInput = new CustomTextField(container.getGraphics().getFont(), 150, 200, 250, 35); usernameInput.setFocused(true); // 默认聚焦 } @Override public void update(GameContainer container, StateBasedGame game, int delta) throws SlickException { usernameInput.update(container.getInput()); } @Override public void render(GameContainer container, StateBasedGame game, Graphics g) throws SlickException { g.drawString("请输入用户名:", 100, 210); usernameInput.render(g); } // 可选:点击文本框获取焦点 @Override public void mousePressed(int button, int x, int y) { boolean isInField = x >= usernameInput.x && x <= usernameInput.x + usernameInput.width && y >= usernameInput.y && y <= usernameInput.y + usernameInput.height; usernameInput.setFocused(isInField); } @Override public int getID() { return stateId; } }
这个自定义组件的优势是完全可控,而且getInputString()会自动处理所有可打印字符,包括Shift键切换大小写、符号输入等,比逐个检测按键高效太多。
内容的提问来源于stack exchange,提问作者Huzaif Ahmed
相关产品推荐
相关产品推荐

