Java-Gaming.org    
Featured games (79)
games approved by the League of Dukes
Games in Showcase (477)
Games in Android Showcase (109)
games submitted by our members
Games in WIP (536)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: [1]
  ignore  |  Print  
  Design Pattern For Game Settings  (Read 2403 times)
0 Members and 1 Guest are viewing this topic.
Offline nellykvist

Senior Newbie





« Posted 2013-09-26 23:09:55 »

I'm creating a game in Java with slick2d library and I would like to implement a design pattern related to game settings (video, sound), so that you can implement all this methods that are needed to load, save settings.. However, I would like someone to suggest me a design-pattern and if possible to make me a short concept of classes, so that I can start from something. For begin, settings will have the following attributes:

Video - resolution, full screen, fps
Sound - is sound on/off, volume
Offline CodeHead

JGO Coder


Medals: 40


From rags to riches...to rags.


« Reply #1 - Posted 2013-09-26 23:31:46 »

Have you looked at one of the existing solutions such as Java's Properties class, or a 3rd arty option like ini4j. Going with the latter option allows you to have individual sections in your settings file for each aspect of your engine that you want to store (such as sound, video, input, etc). There's always the option of using Java's serialization functionality. It all comes down to what your requirements are and what solution best meets them. Cool

Arthur: Are all men from the future loud-mouthed braggarts?
Ash: Nope. Just me baby...Just me.
Offline nellykvist

Senior Newbie





« Reply #2 - Posted 2013-09-26 23:52:27 »

Thanks for that, I've seen that already. Any other suggestions ? I was thinking about Observer or Strategy.
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline Jeremy
« Reply #3 - Posted 2013-09-27 00:10:13 »

Thanks for that, I've seen that already. Any other suggestions ? I was thinking about Observer or Strategy.

Observer Pattern makes sense to me.

Quick Thoughts:

Having the subject be the Module that handles configuration of the video\audio settings, then the appropriate subsystems can register themselves to that module and reflect observed changes. Additionally, you could write a another observer for that module and have it save the configurations to file that you can load up when you restart the game.

So have your render subsystem observe the configuration module\window, when settings have been changed simply reflect them by observation in your rendering subsystem. Same with audio etc...

I wouldn't make the GUI used by the user which configures the game settings the subject. I would definitely abstract the actual storing of configurations etc out (maybe into a singleton, I hate singletons, you could try the service provider which is slightly better) then have the GUI configure that. When the GUI configures that, the observers to that subject will be notified etc...

JevaEngine, Latest Playthrough (This demo is networked with a centralized server model)

http://www.youtube.com/watch?v=rWA8bajpVXg
Offline Troncoso

JGO Coder


Medals: 20



« Reply #4 - Posted 2013-09-27 00:21:44 »

The observer pattern doesn't really make sense for this. This doesn't need a pattern at all. Don't try and use a pattern just for the sake of using a pattern. That's bad practice. Game settings are simple, and you are just trying to complicate it. The Properties class as CodeHead suggested does a great job of maintaining your game settings.

The only "pattern" that I think would be useful (contrary to Jeremy's suggestion) is a Singleton. You don't really want 2 instances of your property manager floating around. And it doesn't integrate with your program at all. You simply send it info to store, and you request info for use in your game.
Offline Jeremy
« Reply #5 - Posted 2013-09-27 03:26:47 »

Saying it doesn't make sense without any justification isn't going to convince me, and it isn't going to convince him either. I provided a full-detailed description for implementation, you just said it won't work because 'we shouldn't use design patterns to solve out problems if they're really simple.' (or something to that effect) Patterns don't complicate anything, they simplify them. Patterns are used to prevent creating tightly coupled and difficult to maintain code. It isn't a valid argument for them to not be applied to a simple module because like all things in a program, simple things grow, simple things must be maintained and simple things will be extended to become more complex.

The Observer pattern is meant to create a loosely couple form of communication between one to many modules.

Global game settings is a subject, one module.

The various subsystems the configurations distributed to are observers, and are the many module.

It makes perfect sense.

You want to add a new setting later down the road for a newly installed subsytem? Easy, just add an observer. Job done. You want to change the way the configurations are stored? No problem, that code is well isolated from the actual configuration module. Since the modules are loosely coupled, there is very little maintenance headache.

I'm not saying you're wrong, but I am saying you haven't done anything to try and convince me.

JevaEngine, Latest Playthrough (This demo is networked with a centralized server model)

http://www.youtube.com/watch?v=rWA8bajpVXg
Offline Troncoso

JGO Coder


Medals: 20



« Reply #6 - Posted 2013-09-27 04:21:07 »

The observer pattern is a one to many relationship (technically it could be many to many). So,  every time you change a setting you are notifying ever registered listener of the change. That is several more method calls than are needed to adjust a single value. Sure,  you could use a condition block to send the notice to a single observer, but at that point,  you are doing what you would have without the pattern anyway, and defeating the purpose of the observer pattern.  

And I have to disagree.  Patterns don't make anything simpler. They are used to organize code in an efficient manner and allow for easy maintenance and upgrade.  That doesn't necessarily make the actual code less or less complicated.

Anyway.  My post wasn't to say you are wrong. Besides a Singleton, what you posted may be the only thing that even sounds reasonable. I'm saying he has the wrong approach.  You shouldn't use pattern if you can't (yourself) recognize a pattern that would fit your problem.  Think about cutting a square peg in half to fit it in a round hole. It works,  but that doesn't make it a good solution. He'll use the first pattern suggested and likely won't even understand it or why it should be used. And patterns definitely make things more complicated if you use them where they aren't needed or use them in the wrong situation.
Offline Jeremy
« Reply #7 - Posted 2013-09-27 04:33:53 »

@Troncoso I mostly agree with what you have said.

That is several more method calls than are needed to adjust a single value.

You could do what Java's util Observable class does (I'm not advocating it's use I am just saying that it solves this by only notifying observers when something significant happens, i.e the configurations are applied etc.) with setChanged() - if invoking ~10 configuration observers ones or twice when the game is running turns into some sort of bottle-neck your code must be doing something very absurd.

Quote
And I have to disagree.  Patterns don't make anything simpler. They are used to organize code in an efficient manner and allow for easy maintenance and upgrade.  That doesn't necessarily make the actual code less or less complicated.

It simplifies one's ability to interpret the code (since the pattern is usually universally understood, at least by the team.) Arguably, it also makes it easier to write if you've already got a pattern in mind to solve the problem.

Quote
Anyway.  My post wasn't to say you are wrong. Besides a Singleton, what you posted may be the only thing that even sounds reasonable. I'm saying he has the wrong approach.  You shouldn't use pattern if you can't (yourself) recognize a pattern that would fit your problem.  Think about cutting a square peg in half to fit it in a round hole. It works,  but that doesn't make it a good solution. He'll use the first pattern suggested and likely won't even understand it or why it should be used. And patterns definitely make things more complicated if you use them where they aren't needed or use them in the wrong situation.

I agree with this point that they should be implemented upon one's own discovery. Patterns are a guide-line (like you suggest) not a concrete solution you can throw anywhere you find it works.

JevaEngine, Latest Playthrough (This demo is networked with a centralized server model)

http://www.youtube.com/watch?v=rWA8bajpVXg
Offline relminator
« Reply #8 - Posted 2013-09-27 07:19:43 »

Is it just me or most Java coders are "pattern-philes"?

I've been on a lot of non-java boards and only in java-centric boards do I see these pattern-first problem solving procedures.
Offline Jeremy
« Reply #9 - Posted 2013-09-27 07:48:53 »

Is it just me or most Java coders are "pattern-philes"?

I've been on a lot of non-java boards and only in java-centric boards do I see these pattern-first problem solving procedures.

Opposed to the "make up your own and hope it works" pattern?

If you know a proved pattern is applicable to your solution, why in god's name would you not use it?

You can go to your co-working and say "I used the observer pattern to... I used the strategy pattern to... I used the adapter pattern to..." and immediately they get a very well illustrated idea of what the solution might be.

Opposed to "I created this method, I've never seen anyone use it before and I hope it works. Sit down with me while we discuss the nitty-gritty details of my implementation instead of moving on to what really matters."

You can't compete with design patterns unless you want to trust your solution against these other well known patterns that have been implemented in a variety of solutions universally because they are known to very well comply to OO design principals and aid in the design of very modular and easily extensible systems. The key is that good design patterns aren't created, they're discovered & proven through the evolution of a complex system.

Any decent program on computer software development will go into at least some basics design patterns.

JevaEngine, Latest Playthrough (This demo is networked with a centralized server model)

http://www.youtube.com/watch?v=rWA8bajpVXg
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline SHC
« Reply #10 - Posted 2013-09-27 08:24:03 »

It's better to use XML now but if you are going to try INI files, please check out my INI parser called JINI

Example usage:

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
JINI ini = new JINI("file-name");

// Reading properties
String property = ini.readProperty("Section-Name", "Property-Name");

// Writing properties
ini.setProperty("Section-Name", "Property-Name", "Property-Value");

// Renaming property
ini.renameProperty("Section-Name", "Old-Property-Name", "New-Property-Name");

// Renaming section
ini.renameSection("Old-Section-Name", "New-Section-Name");

// Saving INI file
BufferedWriter writer = new BufferedWriter(new FileWriter(new File("File-Name")));

writer.write(ini.populate("\n"));

writer.flush();
writer.close();

Hope you find this useful.

Offline Abuse

JGO Coder


Medals: 11


falling into the abyss of reality


« Reply #11 - Posted 2013-09-27 10:06:20 »

Is it just me or most Java coders are "pattern-philes"?

I've been on a lot of non-java boards and only in java-centric boards do I see these pattern-first problem solving procedures.


I suspect it's more to do with Java being used as a teaching language.
At the same time students are learning the language, they're being taught about patterns; it's only natural to try and combine the two.

Make Elite IV:Dangerous happen! Pledge your backing at KICKSTARTER here! https://dl.dropbox.com/u/54785909/EliteIVsmaller.png
Offline relminator
« Reply #12 - Posted 2013-09-27 10:18:21 »

Is it just me or most Java coders are "pattern-philes"?

I've been on a lot of non-java boards and only in java-centric boards do I see these pattern-first problem solving procedures.

Opposed to the "make up your own and hope it works" pattern?

yadda, yadda...
Sigh...

Missed my point.  Tongue

Abuse apparently did get it spot on.  Pointing
Offline nellykvist

Senior Newbie





« Reply #13 - Posted 2013-09-27 10:20:32 »

First of all, thank you guys on quick and constructive replies.

Quote
Patterns are used to prevent creating tightly coupled and difficult to maintain code.
I want to point this out,

However,
Quote
You shouldn't use pattern if you can't (yourself) recognize a pattern that would fit your problem.
I'm not mean to be rude, but I have already first suggested above, in order to get an opinions about it.

However, I've already watched like 2x design pattern tutorials, and I really really got seek of using duplicate codes and many arrays.. I haven't ever used them before in a serious projects, but that's the reason now I want to. I would like to recommend Derek Banas Design Pattern Tutorials http://www.youtube.com/watch?v=vNHpsC5ng_E&list=PLF206E906175C7E07.

Also, thank you SHC, I will take a look at that.
Offline Jeremy
« Reply #14 - Posted 2013-09-27 10:25:13 »

Is it just me or most Java coders are "pattern-philes"?

I've been on a lot of non-java boards and only in java-centric boards do I see these pattern-first problem solving procedures.

Opposed to the "make up your own and hope it works" pattern?

yadda, yadda...
Sigh...

Missed my point.  Tongue

Abuse apparently did get it spot on.  Pointing


To be fair, you didn't make your point very clear at all. You asked a question and stated an observation. That is probably why I missed it? If it was there, it was very poorly made.

These design patterns are used all over the JDK, in fact you can find them in most libraries. They aren't used because Java is a very good OO learning language and people just picked it up there.

Java makes excessive use of the observer pattern in Swing, Decorators for IO etc... They're used because they work.

Outside of Java, and in .Net you'll find them everywhere too.

JevaEngine, Latest Playthrough (This demo is networked with a centralized server model)

http://www.youtube.com/watch?v=rWA8bajpVXg
Offline relminator
« Reply #15 - Posted 2013-09-27 10:36:01 »

Don't get me wrong, I've used patterns extensively in all the languages I code with.  But I use them when I need to not when I want to.
Offline StumpyStrust
« Reply #16 - Posted 2013-09-27 10:47:49 »

I am not a very pro coder. However, I think you are complicating things a bit much. Settings are really trivial. May not be the most "elegant" way of doing things but it works, can be done fast, and has never bitten me in the ass.

Have some class that holds settings. On start up load settings into class. In the game if the user changes things (volume, graphics stuff) and said things do not need a restart, have your code do something like.

1  
2  
3  
4  
if(settingsClass.useWeatherEffects)
{
//do weather effects
}


What you want may apply here, it also may be over kill. If you only ever have 30 collidable objects, there is no need for spatial partitioning. Simple code seems to work the best.

Anyways, good luck on it.

Offline Troncoso

JGO Coder


Medals: 20



« Reply #17 - Posted 2013-09-27 12:28:06 »

If you take a class on design patterns, they will tell you the same thing I did. Just because you learn about patterns, or learn a new one doesn't mean you should go out and try to use it in your next project. Sure,  go find some example problems that are meant specifically for a pattern. Just don't force them where they aren't needed. You make it clear that you are trying to do that here.
Offline Jeremy
« Reply #18 - Posted 2013-09-27 21:28:36 »

If you take a class on design patterns, they will tell you the same thing I did. Just because you learn about patterns, or learn a new one doesn't mean you should go out and try to use it in your next project. Sure,  go find some example problems that are meant specifically for a pattern. Just don't force them where they aren't needed. You make it clear that you are trying to do that here.

The first step to solving any design problem:

1. Identify it
2. Have you solved it before?
3. Has someone else solved it before?
4. Is it possible to apply what you've seen rather than starting from scratch?

No it shouldn't be forced, but it should be identified if it resolves the problem.

The problem was to distribute configurations centralized at one module to many modules without tightly coupling. The Observer pattern does that for you.

JevaEngine, Latest Playthrough (This demo is networked with a centralized server model)

http://www.youtube.com/watch?v=rWA8bajpVXg
Offline Roquen
« Reply #19 - Posted 2013-09-27 22:01:59 »

I'd add some earlier:

-3) Is this the best problem (in the long term, project wide) that I could be dealing with at this moment?
-2) Is this really worth wasting time over vs. doing it the stupidest way possible...hopeful that me or someone else has already written and I can locate faster than wasting any more brain/time power over?
-1) If I'm think about solving a wider problem than I really need...kick myself in the shins.
 0) Understand the problem
....

Protip:  Don't ever take a class on Design Patterns.  Stick to Data structures and Algorithms.  A nice compiler course wouldn't be a bad idea.  Oh...and if you only know one major programming paradigm, then spend time really learning the basics of some other one... preferable one as different as possible from what you know.
Offline Troncoso

JGO Coder


Medals: 20



« Reply #20 - Posted 2013-09-27 23:07:53 »

If you take a class on design patterns, they will tell you the same thing I did. Just because you learn about patterns, or learn a new one doesn't mean you should go out and try to use it in your next project. Sure,  go find some example problems that are meant specifically for a pattern. Just don't force them where they aren't needed. You make it clear that you are trying to do that here.

The first step to solving any design problem:

1. Identify it
2. Have you solved it before?
3. Has someone else solved it before?
4. Is it possible to apply what you've seen rather than starting from scratch?

No it shouldn't be forced, but it should be identified if it resolves the problem.

The problem was to distribute configurations centralized at one module to many modules without tightly coupling. The Observer pattern does that for you.

The 4th is not stated well at all. It's possible to apply a lot of things to a lot of situations. That doesn't necessarily make it helpful, or reduce workload. Sure, I could implement a factory pattern when I have a car that can be 2 different colors in my game. Is that more efficient? Not really, but it's possible.

Again, the observer pattern is overkill. Each setting only effects one value. So, while all the setting values are in one place, each would still, in essence, have to have its own separate listener. The observer pattern is to notify several objects in a certain event, not just one at a time. You may as well make each setting a separate subject and register one observer each.

This is all if we are talking about game configuration settings  like volume, resolution, full screen, and the like. Now, if it's something in game that cause objects to do something as a reaction (think an RTS where, for example, you set the mode to "attack" and each unit needs to receive that message), than sure. But, that's not the case. These configurations don't really even need to tell anyone that they've changed. Whenever you play an audio file, it plays at the volume that was last set, which you just poll your properties file for. You don't need to tell the audio player that the volume changed, unless you just want to set a local volume variable. No one else cares about that value, though. When you turn on AA, you don't really even need to tell anyone then, either. Since that should be some persistent state, than all graphics will automatically be drawn with AA on the next frame. Maybe you tell the rendering context, but again, you are effecting a single object due to a single value change.

There's nothing complicated about game settings, and it doesn't get complicated regardless how many you add. You add the value to a file, then you access the file to get the value. You add a new value, you instantly have a new setting. Simple as that. That's already completely decoupled, and you didn't even need a pattern. Though, I would still argue that a Singleton would be a good idea here for easier access to the settings file.

At this point, I guess it's just opinion. I've detailed my point as I failed to do in my first point. If you really want to believe an observer pattern would be more useful here that no pattern at all, than I guess I don't technically have a right to judge that as wrong.

And @Roquen, for anyone that plans to get a degree in Computer Science (like I did), a class in Design Patterns generally isn't an option. Even if it is, there will be a Software Engineering course you have to take that will throw patterns into the mix. To say you shouldn't take the class though is something I disagree with. Ever taken one? You learn patterns a lot better than just browsing the Internet. And a lot more. Sure, you can look at a list of 50 patterns online, but that doesn't mean you understand how to use them.

And to add to your "protip" if you want a language that will really test your logic skills, dabble in Prolog. Logic, to me, is the most important skill a programmer needs to refine. This language does that for you better than any other.
Offline xsvenson
« Reply #21 - Posted 2013-09-27 23:19:01 »

You guys are getting too carried away arguing about trivialities.

Make something that barely works. Once You have a little experience You'll see the shortcomings, then You'll make it better. After a few iterations it's a *good solution*. With some more experience and time You start using the *good solution* everywhere. After a few years, You'll notice that it has a name. It's called "whatever-pattern-it-was-that-You-were-using"

The problem with teaching patterns and having the lecture is that they mold Your brain into thinking everything patterns. And then You are "the pattern guy" who only talks and writes code in patterns. No... just don't.

And, for the love of code, don't argue about it. Just write code and name the pattern later.

My suggestion for the OP: Don't ask about patterns ( Look at this thread ).

“The First Rule of Program Optimization: Don't do it. The Second Rule of Program Optimization (for experts only!): Don't do it yet.” - Michael A. Jackson
Offline Troncoso

JGO Coder


Medals: 20



« Reply #22 - Posted 2013-09-27 23:30:27 »

That's the thing about a class; they beat into your head not to use patterns where they aren't needed. My teacher's analogy:

"If you give a 5 year old a hammer, suddenly everything needs to be hammered. Don't be a 5 year old with a new hammer".
Offline Roquen
« Reply #23 - Posted 2013-09-28 00:07:00 »

It's not just taking a class...there's a mindset that "design patterns" are interesting.  They aren't.  They're nothing more than some skeleton code-snippets that might be interesting in a given case in a given language for a given problem and design need.  Reread the first post and say yourself "Why on earth are we talking about design patterns"?  Because we shouldn't be.  It's taking a trivial problem and making it difficult.  I could go on-and-on about design patterns, but I've done that enough on this forum.
Offline DrZoidberg

Senior Member


Medals: 15



« Reply #24 - Posted 2013-09-28 01:33:29 »

Ok, here is the most simple solution I could think of.
Everything is hard coded. Not recommended for large projects, but for simple games it should be sufficient.
This example program can be compiled and run as it is.

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
36  
37  
38  
39  
40  
41  
42  
43  
44  
45  
46  
47  
48  
49  
50  
51  
52  
53  
54  
55  
56  
57  
58  
59  
60  
61  
62  
63  
64  
65  
66  
67  
68  
69  
70  
71  
72  
73  
74  
75  
76  
77  
78  
79  
80  
81  
82  
83  
84  
85  
86  
87  
88  
89  
90  
91  
92  
93  
94  
95  
96  
97  
98  
99  
100  
101  
102  
103  
104  
105  
106  
107  
108  
109  
110  
111  
112  
113  
114  
115  
116  
117  
118  
119  
import java.io.*;
import java.awt.Dimension;
import java.util.Scanner;

class GameFrame {
    Dimension resolution = new Dimension(800,600);
    boolean isFullScreen = false;
    double fps = 60;
   
    Dimension getResolution() {
        return resolution;
    }
    void setResolution(Dimension resolution) {
        this.resolution = resolution;
    }
    boolean isFullScreen() {
        return isFullScreen;
    }
    void setFullScreen(boolean isFullScreen) {
        this.isFullScreen = isFullScreen;
    }
    double getFPS() {
        return fps;
    }
    void setFPS(double fps) {
        this.fps = fps;
    }
}

class AudioSystem {
    boolean isSoundOn = true;
    double volume = 100;
   
    boolean isSoundOn() {
        return isSoundOn;
    }
    void setSoundOn(boolean isSoundOn) {
        this.isSoundOn = isSoundOn;
    }
    double getVolume() {
        return volume;
    }
    void setVolume(double volume) {
        this.volume = volume;
    }
}

class Game {
    GameFrame gameFrame = new GameFrame();
    AudioSystem audioSystem = new AudioSystem();
   
    GameFrame getGameFrame() {
        return gameFrame;
    }
    AudioSystem getAudioSystem() {
        return audioSystem;
    }
   
    public static void main(String[] args) {
        Game game = new Game();
        Tools.writeSettings("config.txt", game);
        game.getGameFrame().setFPS(100);
        game.getAudioSystem().setVolume(50);
        System.out.println(game.getGameFrame().getFPS());
        System.out.println(game.getAudioSystem().getVolume());
        Tools.readSettings("config.txt", game);
        System.out.println(game.getGameFrame().getFPS());
        System.out.println(game.getAudioSystem().getVolume());
    }
}

class Tools {
    static void writeSettings(String fileName, Game game) {
        PrintWriter out = null;
        try {
            out = new PrintWriter(fileName);
            GameFrame gameFrame = game.getGameFrame();
            AudioSystem audioSystem = game.getAudioSystem();
            Dimension resolution = gameFrame.getResolution();
            out.println("resolution: " + resolution.width + ", " + resolution.height);
            out.println("isFullScreen: " + gameFrame.isFullScreen());
            out.println("fps: " + gameFrame.getFPS());
            out.println("isSoundOn: " + audioSystem.isSoundOn());
            out.println("volume: " + audioSystem.getVolume());
            out.flush();
            out.close();
        } catch(IOException e) {
            e.printStackTrace();
        } finally {
            if(out != null) out.close();
        }
    }
    static void readSettings(String fileName, Game game) {
        Scanner in = null;
        try {
            in = new Scanner(new File(fileName)).useDelimiter("\\s+|\\s*:\\s*|\\s*,\\s*");
            GameFrame gameFrame = game.getGameFrame();
            AudioSystem audioSystem = game.getAudioSystem();
            while(in.hasNext()) {
                String str = in.next();
                if(str.length() == 0) continue;
                if(str.equals("resolution")) gameFrame.setResolution(
                    new Dimension(Integer.parseInt(in.next()), Integer.parseInt(in.next())));
                else if(str.equals("isFullScreen")) gameFrame.setFullScreen(
                    Boolean.parseBoolean(in.next()));
                else if(str.equals("fps")) gameFrame.setFPS(
                    Double.parseDouble(in.next()));
                else if(str.equals("isSoundOn")) audioSystem.setSoundOn(
                    Boolean.parseBoolean(in.next()));
                else if(str.equals("volume")) audioSystem.setVolume(
                    Double.parseDouble(in.next()));
            }
        } catch(IOException e) {
            e.printStackTrace();
        } finally {
            if(in != null) in.close();
        }
    }
}
Offline DrZoidberg

Senior Member


Medals: 15



« Reply #25 - Posted 2013-09-28 02:19:00 »

Now here is another example. This time it uses a completely different strategy. It stores all settings in a HashMap. Also it uses the Observer pattern.

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
36  
37  
38  
39  
40  
41  
42  
43  
44  
45  
46  
47  
48  
49  
50  
51  
52  
53  
54  
55  
56  
57  
58  
59  
60  
61  
62  
63  
64  
65  
66  
67  
68  
69  
70  
71  
72  
73  
74  
75  
76  
77  
78  
79  
80  
81  
82  
83  
84  
85  
86  
87  
88  
89  
90  
91  
92  
93  
94  
95  
96  
97  
98  
99  
100  
101  
102  
103  
104  
105  
106  
107  
108  
109  
110  
111  
112  
113  
114  
115  
116  
117  
118  
119  
120  
121  
122  
123  
124  
125  
126  
127  
128  
import java.io.*;
import java.util.*;
import java.awt.Dimension;

abstract class SettingListener<T> {
    String name;
   
    SettingListener(String name) {
        this.name = name;
    }
   
    String getName() {
        return name;
    }
   
    abstract void reactToChange(T oldValue, T newValue);
}

class GameFrame {
    Game game;
    GameFrame(Game game) {
        this.game = game;
        game.changeSetting("resolutionX", 800.0);
        game.changeSetting("resolutionY", 600.0);
        game.changeSetting("isFullScreen", false);
        game.changeSetting("fps", 60.0);
    }
}

class AudioSystem {
    Game game;
    AudioSystem(Game game) {
        this.game = game;
        game.changeSetting("isSoundOn", true);
        game.changeSetting("volume", 100.0);
        game.addSettingListener(new SettingListener<Double>("volume") {
            void reactToChange(Double oldValue, Double newValue) {
                System.out.println("volume was changed from " + oldValue + " to " + newValue);
            }
        });
    }
}

class Game {
    Map<String, Object> settings = new HashMap<>();
    List<SettingListener> settingListeners = new ArrayList<>();
   
    void addSettingListener(SettingListener listener) {
        settingListeners.add(listener);
    }
   
    Object getSetting(String name) {
        return settings.get(name);
    }
   
    @SuppressWarnings("unchecked")
    void changeSetting(String name, Object value) {
        Object oldValue = settings.get(name);
        settings.put(name, value);
        for(SettingListener listener: settingListeners) {
            if(listener.getName().equals(name))
                listener.reactToChange(oldValue, value);
        }
    }
   
    GameFrame gameFrame = new GameFrame(this);
    AudioSystem audioSystem = new AudioSystem(this);
   
    GameFrame getGameFrame() {
        return gameFrame;
    }
    AudioSystem getAudioSystem() {
        return audioSystem;
    }
   
    public static void main(String[] args) {
        Game game = new Game();
        Tools.writeSettings("config.txt", game);
        game.changeSetting("fps", 100.0);
        game.changeSetting("volume", 50.0);
        System.out.println(game.getSetting("fps"));
        System.out.println(game.getSetting("volume"));
        Tools.readSettings("config.txt", game);
        System.out.println(game.getSetting("fps"));
        System.out.println(game.getSetting("volume"));
    }
}

class Tools {
    static void writeSettings(String fileName, Game game) {
        PrintWriter out = null;
        try {
            out = new PrintWriter(fileName);
            for(String name: game.settings.keySet()) {
                Object value = game.settings.get(name);
                out.println(name + ": " + value);
            }
            out.flush();
            out.close();
        } catch(IOException e) {
            e.printStackTrace();
        } finally {
            if(out != null) out.close();
        }
    }
    static void readSettings(String fileName, Game game) {
        Scanner in = null;
        try {
            in = new Scanner(new File(fileName)).useDelimiter("\\s+|\\s*:\\s*");
            while(in.hasNext()) {
                String name = in.next();
                if(name.length() == 0) continue;
                String value = in.next();
                Double doubleValue = null;
                try {
                    doubleValue = Double.valueOf(value);
                } catch(NumberFormatException e) {
                }
                if(doubleValue != null) game.changeSetting(name, doubleValue);
                else game.changeSetting(name, value);
            }
        } catch(IOException e) {
            e.printStackTrace();
        } finally {
            if(in != null) in.close();
        }
    }
}
Offline Jeremy
« Reply #26 - Posted 2013-09-28 02:40:07 »

That's the thing about a class; they beat into your head not to use patterns where they aren't needed. My teacher's analogy:

"If you give a 5 year old a hammer, suddenly everything needs to be hammered. Don't be a 5 year old with a new hammer".

You're right when you say this has essentially boiled down to opinion.

You don't ask yourself "do I need a design pattern NOW?" No, because now you don't. If all you're only concerned about is the now, you mid as well make everything concrete, throw away your OO design principals and forget about patterns all together.

I assume you are implying to include the future in the "do I need a design pattern?" I am just highlighting that point.

Quote
Sure, I could implement a factory pattern when I have a car that can be 2 different colors in my game. Is that more efficient? Not really, but it's possible.

If you're trying to present a case where it isn't efficient, that case doesn't illustrate at all what the abstract factory pattern or factory method pattern aims to solve. If you've coupled your object creation code with another class that could otherwise have been closed for change, you can't say that this class is closed for changes and you now have a maintenance issue whenever you've got a new colour. Is it a problem? It depends, if your building very simple code, probably not at all. If you're building a framework for other developers and there may be more car colours, YES definitely. They have to hack crap into your instantiation code every time they want a new colour.

You should ask yourself will this module need to be expanded in the future and will expanding the function of this module become an issue (does your class violate the open\closed principal?) If it does, and there is a violation of this principal (or various other common design principals) chances are that yes, you will have trouble expanding on to the module later.

Those violations are the problem, and the solutions to those problems may have already been solved & proven. You can develop your own solution of course, but it doesn't hurt to have a library of them in your head.

By not using an observer pattern for configurations, the OPs code cannot be 'closed for changes and open for expansion.' Is that a problem? Will it need to be expanded later? That's his call not ours.

JevaEngine, Latest Playthrough (This demo is networked with a centralized server model)

http://www.youtube.com/watch?v=rWA8bajpVXg
Offline Troncoso

JGO Coder


Medals: 20



« Reply #27 - Posted 2013-09-28 03:52:20 »

As I said, this being like the third time, for this specific scenario (game settings), yes, you can implement them without a pattern and still be closed to modification. The "subject" is nothing more than a list of values. You pop in a new value, you have a new setting. You don't have to change any code, only expand to utilize that new value. Seriously, there's nothing about that where the observer pattern makes it any more de-coupled.

Anyway. I guess I'm done here. You realize that if the OP didn't explicitly ask for a pattern, that one probably would have never even been suggested? I applaud you for simply trying to give him what he wants. I just strongly believe he doesn't quite understand what he's asking for. Roquen is right. This problem is easy enough to solve without a pattern, and it's not something that will get more complex as the aspect evolves. There's no need to even be talking about them (besides the fact that it's the exact topic of this thread).
Offline Jeremy
« Reply #28 - Posted 2013-09-28 04:03:01 »

Well I'm done too, with a last note:

The observer pattern doesn't solve the coupling in the storing of the configuration (there isn't any there, I agree), but coupling in the distribution of the modifications to those configurations from the subject to the subsystems in which such changes must be reflected in real-time. You're point about it not helping (in terms of coupling) targets the wrong aspect of the design.

It probably wouldn't have been suggested since the thread wouldn't exist? Since the question is in the thread's title.

JevaEngine, Latest Playthrough (This demo is networked with a centralized server model)

http://www.youtube.com/watch?v=rWA8bajpVXg
Pages: [1]
  ignore  |  Print  
 
 
You cannot reply to this message, because it is very, very old.

 

Add your game by posting it in the WIP section,
or publish it in Showcase.

The first screenshot will be displayed as a thumbnail.

CogWheelz (18 views)
2014-07-30 21:08:39

Riven (25 views)
2014-07-29 18:09:19

Riven (15 views)
2014-07-29 18:08:52

Dwinin (13 views)
2014-07-29 10:59:34

E.R. Fleming (33 views)
2014-07-29 03:07:13

E.R. Fleming (12 views)
2014-07-29 03:06:25

pw (43 views)
2014-07-24 01:59:36

Riven (44 views)
2014-07-23 21:16:32

Riven (30 views)
2014-07-23 21:07:15

Riven (31 views)
2014-07-23 20:56:16
List of Learning Resources
by SilverTiger
2014-07-31 18:29:50

List of Learning Resources
by SilverTiger
2014-07-31 18:26:06

List of Learning Resources
by SilverTiger
2014-07-31 13:54:12

HotSpot Options
by dleskov
2014-07-08 03:59:08

Java and Game Development Tutorials
by SwordsMiner
2014-06-14 00:58:24

Java and Game Development Tutorials
by SwordsMiner
2014-06-14 00:47:22

How do I start Java Game Development?
by ra4king
2014-05-17 11:13:37

HotSpot Options
by Roquen
2014-05-15 09:59:54
java-gaming.org is not responsible for the content posted by its members, including references to external websites, and other references that may or may not have a relation with our primarily gaming and game production oriented community. inquiries and complaints can be sent via email to the info‑account of the company managing the website of java‑gaming.org
Powered by MySQL Powered by PHP Powered by SMF 1.1.18 | SMF © 2013, Simple Machines | Managed by Enhanced Four Valid XHTML 1.0! Valid CSS!