Integrating Swing in a simple text adventure game

孤街浪徒 提交于 2019-12-02 12:51:51
Chewtoy

First, regarding including code, you should take a look at https://stackoverflow.com/help/mcve for how to help us help you.

Now, given that you haven't provided any code (yet!) giving suggestions on how you should structure your program is a bit tricky. But I'll make an attempt anyways and might edit the answer when you've provided a MWE.

In your case, JTextArea is really just a fancy System.out.print as you will only use it to display the text that your adventure game outputs (if I'm understanding you correctly). So basically, you can write a method that accepts a string, and that method will append that string to your JTextArea. Then just replace your current output-lines with this method.

Then you have your JTextField which you want to replace your (I'm guessing) Scanner(System.in) with. I assume you know how to set up an action listener that responds to Enter or a submit-button. How to set these up is not all that strange, and lots of guides talk about how to do it. https://docs.oracle.com/javase/tutorial/uiswing/components/textfield.html gives a good example.

Now, in general regarding the structure of your program. You do not want to be dependent on how the user enters the text or how you display it. What I mean with this is that you do not want input- or display-logic to meddle with your game (business) logic. Your game logic should just receive input, from where ever, and output it to where ever. How and what the calling functions then decide to do with the information is not for the game logic to care about.

So, applied to the method names you posted. I assume run() is where you kick things off. As you have output that you always want to display, you might want to pass in an interface here that has the method print(string) (or the like) which should be a method that prints the text to whatever text-element is used to display the text, be it System.out or JTextArea. The run() method never needs to know. handleCommand() should also just accept a value (I assume a String) and handle it like it should, no matter who or what called it.

I'm having trouble giving you more advice with no code. But my general recommendation is: Don't mix presentation logic with business logic. And give each method as little info as possible, because giving them more than they actually need usually leads to a less flexible flow and structure.


EDIT now that some code has been added.

I know how to print output to the JTextArea instead of to the console. My issue is how exactly to get handleCommand() to work with actionPerformed() in the Frame class

Go with the actionPerformed() approach. I recommend this because you won't have to bother with as much if you decide to Thread your application sometime in the future (multiplayer?). https://docs.oracle.com/javase/tutorial/uiswing/events/actionlistener.html gives some good info about how to write your listener. But I'll give you some suggestion code as well.

...
area.setEditable(false);

field = new JTextField(20);
field.addActionListener(new SendText());    
....

class SendText implements ActionListener{
    public void actionPerformed(ActionEvent ae){
        if(ae.getSource() == field){
            String str = field.getText();
            if(!str.equals("")){
                commandHandler.handle(str);
            }
        }
    }
}

And then rewrite your run() method

public void run(){
   ui.print(commandHandler.listCommands());

   while(true){
       if(commandHandler.continue()){
           ui.print(commandHandler.events());
       }
   }
}

So now you have a very small run() method that has no real tie-in to either the logic or the display. ui.print(str) is a method that your UI class (Frame in your case) that just appends what ever string is sent to it to it's drawing area, be it System.out or a JTextArea.

commandHandler is new. This is where your game logic should be. It has a method handle(string) which is your old handleCommand(string). It has a continue() method that returns a boolean. The boolean should be set to true whenever you want the story to continue, eg when the user enters a command. And finally events() (which is a bad name) that returns what has happened since the last command was sent in and gives the users options on what to do next. I've not done an implementation of that, as I just want to give the concept to you. The UI doesn't do any logic processing. The run() method doesn't expect anything, it just keeps checking if continue() is true. commandHandler is where all the bizz is.

Now, you do have a infinite loop running. So if you get any performance issues you could look into Thread. This model should support a move to it.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!