"Cowboy Coders" shoot from the hip. They're lone wolves, programming heroes. They're respected for their work ethic, programming speed, and brilliance - but hated for their unreadable code, lack of standards, and arrogance.
There are many types of 'bad' programmers. The 'cowboy' label is used if the bad programmer has a high opinion of himself (deserved or not), ignores standards, and writes brilliant (if complex and unmaintainable) code. Cowboys aren't stupid, but they might be ignorant. They believe strongly in standards - but only their own. They rarely work well in teams, preferring to work alone. Many cowboys are also workaholics.
One of the perceived strengths of a cowboy coder is their ability to dive into tricky bugs, figure out what's going on (maybe spending all night working on it), and coming up with a complex and brilliant solution. Especially when a deadline is near.
One of the most hated traits of the cowboy is his habit of loudly disrespecting his fellows. This is one reason why cowboys work alone; they can't stand working with others, and others can't stand working with them.
But "Cowboy Coder" is a stereotype. Real people are rarely like that. It's fun to make up or read lists of programmer types, and "cowboy" is one of the stereotypes that I've heard the most. The qualities I've found distasteful in other coders are rarely like the perceived weaknesses of cowboys, and the strengths of good coders I've worked with are more complex that the "work hard" and "brilliant" attributes given to cowboys. Next time, I'll cover the strengths of weaknesses of cowboys that really matter in my next post.
Thursday, May 20, 2010
Saturday, April 24, 2010
Fun RPG Combat, Part 2
In my previous post on making rpg combat fun, I talked about some high-level principles behind what's fun and what's not. This time, I delve into specifics.
Rogue-Like RPGs
Rogue-like games make combat fun by not telling you the mechanics. A lot of the 'fun' in a roguelike is learning the rules; what various creatures do, how useful your various abilities are, when you should run, when you should fold, etc etc. For people that like learning mechanics that way, roguelikes are a lot of fun. For people that skew more towards achievers on the Bartle scale, roguelikes can be frustrating. I think the success of WoW shows that there's tons of achievers out there. As an explorer, I like discovering mechanics -- but I also find Rogue-like games frustrating, I think in part because the fun bit of the mechanic is hidden. The game isn't really about discovering mechanics; it's about getting to the bottom of the dungeon and 'winning', which is an achievement. Ultimately, I think achievement is the strongest motivator. So let's leave rogue-likes behind.
Achievement RPGs
In achievement-oriented RPGs, players can have dozens or hundreds of hours of new abilities, creatures, and environments to explore. The fundamental mechanic of these games is always combat. Combat has to be fun, and they make it so by changing it up. Sometimes just cosmetically (with new environments and different-looking creatures), other times with new mechanics. New mechanics include new player abilities, new creature abilities, environmental restrictions (such as a pool of lava or spinning blades that one must avoid and might push an enemy into), and complications like adding a second creature to fight -- forcing the player to not just kill one target, but figure out how to juggle two targets. Mixing two types of targets together creates a huge explosion in the puzzle space. And when the player gains another dozen abilities, they might tackle that exact same mix of targets in an entirely new way.
It's easy to see why RPGs give players new abilities, and then pit them against enemies with ever-changing abilities, too. The game is combat, everything else is window dressing. Make combat interesting, and the player will suffer your bad dialog, predictable plots, and boring tradeskills. And if your abilities are balanced, bam, instant puzzle.
Power Trips
Another aspect of achievement games is the power trip. That's why games have levels. Not because the badge is 'good gameplay', or some sort of esoteric bullshit. But because, when you're level 20, you can go back to that level 1 orc and pound the shit out of him. The tough meany that killed you three times when you were level 19 becomes less of a challenge after you level up to 20. He's not really difficult at all any more, because you now know how the fight goes, plus you've got a little bit of extra hp, ac, and damage output. It feels like a challenge, because you're focused on the fight.
(That, btw, is the point I made in the previous post. If you're busy executing your combat plan, you don't have time to think about bad dialog or predictable plots. Keep the player focused on the combat puzzle, even if his chance of success is 99%, and he thinks it's challenging and fun.)
The Grind
RPGs can become boring if you're forced to 'grind.' But a grind is no different than any other part of the game; you're still in combat 90% of the time. But a grind is combat that isn't new. It's you against the exact same enemies you've fought before, with the exact same abilities. Neither you nor them have different powers. You've solved the puzzle, and now you're asked to solve it over and over again.
I usually got around that boring bit of grinding by focusing on a meta-issue. Not winning the combat itself, but winning faster. By figuring out a circuit through a dozen mobs that lets me kill them as fast as possible. By finding clusters of the mob that I need to kill so that I am not waiting for them to respawn, and I'm not wasting too much time travelling from one group to another. I was able to choose and pursue these goals myself; most players, I think, don't. If you can make that meta goal explicit, it might be one way of alleviating the grind.
The obvious solution, of course, is new abilities or cosmetics. Yet that's kind of the point here; sometimes, for some reason, players will want to go back and kill the same creature over and over again. Normally the game shepherds players into new areas. Some games (Lineage comes to mind here) fail at giving new abilities to either the player or his quarry. But most designers know that's a design that turns off a lot of players; they know that they need to give the player either a new ability, a new opponent, or at least new scenery in which to solve the same puzzle.
What happens when you can't? There is no solution, of course. It's more of a statement about the goals that the game has set up. In order to make money in World of Warcraft, I'd go kill elementals for hours. Usually I could only stand about an hour at a time, but I spent dozens of hours killing those creatures over and over again. Eventually, Blizzard figured out that players were grinding for cash. They solved this problem not by somehow making the grind more fun (my argument is that's impossible), but by adding ways to get cash that were both more efficient and more fun.
There's one other issue I'd like to talk about, an interaction between quests and combat that can make combat unfun.
Press the Button
Say you've got a quest to go collect 10 wolf pelts. Sure, ok, go kill wolves until you've got 10 pelts. You play the combat minigame, usually against a new creature, and have fun. Turn in your pelts, which is where the big XP is, and move on.
But what about the quests where the goal isn't to kill or collect drops, but do something completely different? Say you need to hit a button in the middle of a field, but there's a bunch of wolves there. Now the wolves are in your way. You can solve the puzzle of how to kill them, but it's not really your goal. A good designer can make 'press the button' into an interesting story, but ultimately the player wants the quest reward, not the quest text. The 'button' could be a gravestone they need to read, or an altar where they need to perform a ritual, or a dropped scroll that they need to pick up. Players think of these tasks as different and interesting, but fundamentally they're just pressing a button. Run over here, hover your mouse, and click. The game spits out some flavor text, but really it's just a button.
And many players skip quest text altogether, using add-ons to tell them what combat puzzle they need to go solve next.
Is it better to ask players to go kill 10 wolves? Or ask him to do something such that the player chooses to engage in combat because those wolves are effin annoying and keep interrupting him while he's trying to press the button? In the button case, the player might see combat as an annoyance. I remember many times in WoW where we had to go press some button, and I worked with group-mates to train the mobs out of there, or stealth through the encounter, or whatever, to avoid combat. Combat should have been the game, but I was inventing a new game to avoid it.
And I think that's the answer. Tell the player to kill "the five guards" then press the button, or give them mechanics to avoid combat altogether, so that they get the thrill of 'cleverly' avoiding combat. You want your players to have happy emotions, to think that they've achieved something tricky or clever. Give them the tools so that, however they're solving the quest, what they're engaging in is not clearing out an annoyance but positively engaging in a new puzzle.
see also: Bartle's book on designing virtual worlds
Rogue-Like RPGs
Rogue-like games make combat fun by not telling you the mechanics. A lot of the 'fun' in a roguelike is learning the rules; what various creatures do, how useful your various abilities are, when you should run, when you should fold, etc etc. For people that like learning mechanics that way, roguelikes are a lot of fun. For people that skew more towards achievers on the Bartle scale, roguelikes can be frustrating. I think the success of WoW shows that there's tons of achievers out there. As an explorer, I like discovering mechanics -- but I also find Rogue-like games frustrating, I think in part because the fun bit of the mechanic is hidden. The game isn't really about discovering mechanics; it's about getting to the bottom of the dungeon and 'winning', which is an achievement. Ultimately, I think achievement is the strongest motivator. So let's leave rogue-likes behind.
Achievement RPGs
In achievement-oriented RPGs, players can have dozens or hundreds of hours of new abilities, creatures, and environments to explore. The fundamental mechanic of these games is always combat. Combat has to be fun, and they make it so by changing it up. Sometimes just cosmetically (with new environments and different-looking creatures), other times with new mechanics. New mechanics include new player abilities, new creature abilities, environmental restrictions (such as a pool of lava or spinning blades that one must avoid and might push an enemy into), and complications like adding a second creature to fight -- forcing the player to not just kill one target, but figure out how to juggle two targets. Mixing two types of targets together creates a huge explosion in the puzzle space. And when the player gains another dozen abilities, they might tackle that exact same mix of targets in an entirely new way.
It's easy to see why RPGs give players new abilities, and then pit them against enemies with ever-changing abilities, too. The game is combat, everything else is window dressing. Make combat interesting, and the player will suffer your bad dialog, predictable plots, and boring tradeskills. And if your abilities are balanced, bam, instant puzzle.
Power Trips
Another aspect of achievement games is the power trip. That's why games have levels. Not because the badge is 'good gameplay', or some sort of esoteric bullshit. But because, when you're level 20, you can go back to that level 1 orc and pound the shit out of him. The tough meany that killed you three times when you were level 19 becomes less of a challenge after you level up to 20. He's not really difficult at all any more, because you now know how the fight goes, plus you've got a little bit of extra hp, ac, and damage output. It feels like a challenge, because you're focused on the fight.
(That, btw, is the point I made in the previous post. If you're busy executing your combat plan, you don't have time to think about bad dialog or predictable plots. Keep the player focused on the combat puzzle, even if his chance of success is 99%, and he thinks it's challenging and fun.)
The Grind
RPGs can become boring if you're forced to 'grind.' But a grind is no different than any other part of the game; you're still in combat 90% of the time. But a grind is combat that isn't new. It's you against the exact same enemies you've fought before, with the exact same abilities. Neither you nor them have different powers. You've solved the puzzle, and now you're asked to solve it over and over again.
I usually got around that boring bit of grinding by focusing on a meta-issue. Not winning the combat itself, but winning faster. By figuring out a circuit through a dozen mobs that lets me kill them as fast as possible. By finding clusters of the mob that I need to kill so that I am not waiting for them to respawn, and I'm not wasting too much time travelling from one group to another. I was able to choose and pursue these goals myself; most players, I think, don't. If you can make that meta goal explicit, it might be one way of alleviating the grind.
The obvious solution, of course, is new abilities or cosmetics. Yet that's kind of the point here; sometimes, for some reason, players will want to go back and kill the same creature over and over again. Normally the game shepherds players into new areas. Some games (Lineage comes to mind here) fail at giving new abilities to either the player or his quarry. But most designers know that's a design that turns off a lot of players; they know that they need to give the player either a new ability, a new opponent, or at least new scenery in which to solve the same puzzle.
What happens when you can't? There is no solution, of course. It's more of a statement about the goals that the game has set up. In order to make money in World of Warcraft, I'd go kill elementals for hours. Usually I could only stand about an hour at a time, but I spent dozens of hours killing those creatures over and over again. Eventually, Blizzard figured out that players were grinding for cash. They solved this problem not by somehow making the grind more fun (my argument is that's impossible), but by adding ways to get cash that were both more efficient and more fun.
There's one other issue I'd like to talk about, an interaction between quests and combat that can make combat unfun.
Press the Button
Say you've got a quest to go collect 10 wolf pelts. Sure, ok, go kill wolves until you've got 10 pelts. You play the combat minigame, usually against a new creature, and have fun. Turn in your pelts, which is where the big XP is, and move on.
But what about the quests where the goal isn't to kill or collect drops, but do something completely different? Say you need to hit a button in the middle of a field, but there's a bunch of wolves there. Now the wolves are in your way. You can solve the puzzle of how to kill them, but it's not really your goal. A good designer can make 'press the button' into an interesting story, but ultimately the player wants the quest reward, not the quest text. The 'button' could be a gravestone they need to read, or an altar where they need to perform a ritual, or a dropped scroll that they need to pick up. Players think of these tasks as different and interesting, but fundamentally they're just pressing a button. Run over here, hover your mouse, and click. The game spits out some flavor text, but really it's just a button.
And many players skip quest text altogether, using add-ons to tell them what combat puzzle they need to go solve next.
Is it better to ask players to go kill 10 wolves? Or ask him to do something such that the player chooses to engage in combat because those wolves are effin annoying and keep interrupting him while he's trying to press the button? In the button case, the player might see combat as an annoyance. I remember many times in WoW where we had to go press some button, and I worked with group-mates to train the mobs out of there, or stealth through the encounter, or whatever, to avoid combat. Combat should have been the game, but I was inventing a new game to avoid it.
And I think that's the answer. Tell the player to kill "the five guards" then press the button, or give them mechanics to avoid combat altogether, so that they get the thrill of 'cleverly' avoiding combat. You want your players to have happy emotions, to think that they've achieved something tricky or clever. Give them the tools so that, however they're solving the quest, what they're engaging in is not clearing out an annoyance but positively engaging in a new puzzle.
see also: Bartle's book on designing virtual worlds
Monday, April 19, 2010
Menu State Management in Games
I've written about high-level game state management before, but I didn't provide any direct code. I got a couple questions about this recently, so I decided to put a post together.
Menu management is a very clear example of the State pattern. Each different page in the menu is a different concrete subclass derived from a common State base class and managed by a Context. There's a few tricks that make this a bit easier.
For example, menus are often nested. This suggests using a Stack pattern for the context. I generally have a GameContext class that has Push, Pop, and Switch methods. They can either take a State subclass instance as a parameter, or some sort of identifier. I think this choice is 50-50; I don't have a clear preference for either one.
There's two ways of doing identifiers. Again, I don't have a clear preference here either. I tend to switch back & forth between these two solutions. (1) Add an ID in the class itself, e.g.
The Context itself also tends to be an instance of the Singleton pattern, with some public, global access. Pop, Push, and Switch might be static methods, for example; I find that means less code and complexity on the client side. (Never trust anyone using your class to be able to code their way out of a paper bag! Simpler interfaces are better.)
I usually start with a simple, copy-n-pasted examples of the different Menu classes. For example, they'll have their own Scenes for 3D objects and 2D UI bits. This is usually easier, faster, and more reliable than trying to develop the Most Awesomest Generic Menu Class Ever. The UI manager will take button clicks, and then call Context.Switch() or Pop() as needed, or Push() if the user hits the 'previous menu' button.
Game startup, then, will do stuff like initialize the 3D environment, game asset libraries, sound, etc, then start up the game state context and tell it which State to start with, which is often a CompanyLogoState. Usually I have game startup then call Context.Run, which does a simple loop of CurrentState.HandlePendingEvents, CurrentState.Draw, and CurrentState.Tick. There's some complexity there with handling events, being able to handle Push and Pop, updating the state at the right time, etc.
CompanyLogoState.Tick() will usually draw a 2D company logo, gradually brightening from black to white, holding, then back to black. When it gets to black, Tick() will call Context.Switch( GameTitleState.kStateId ), which pops the CompanyLogo off the stack and puts GameTitle in its place. That state does the same thing -- bring up the lights, so the title screen, then switch to the Main Menu state. Both the CompanyLogo and GameTitle states will move on to the next state if a key is pressed; that's done in their HandlePendingEvents() method. Eventually, one of the various Menu states (MainMenu, PlayGameMenu, LoadSavedGameMenu / StartNewGameMenu, etc etc) will need to actually start the game. That's cake: just have it call Context.Push( GameState.kMenuId ). And if the game needs to switch to a full-screen menu at some point, it can pause itself and push a new state onto the stack: Context.Push( SaveGameMenu.kMenuId ). Of course it will be important to plan out all of your various menus and states, and make sure you don't have any recursive loops.
Using this pattern, all of the various high-level states in the game are handled through the Context, which also does event handling and rendering. I've even once modified the process to work in a nested window as well - such as when you bring up the 'game menu' while a game is in progress, which doesn't back out into a full-screen menu but instead shows the game in the background, paused & faded.
As with any code, start simple. Copy n paste as needed. When you need more complexity, well-written code is easy to extend.
Menu management is a very clear example of the State pattern. Each different page in the menu is a different concrete subclass derived from a common State base class and managed by a Context. There's a few tricks that make this a bit easier.
For example, menus are often nested. This suggests using a Stack pattern for the context. I generally have a GameContext class that has Push, Pop, and Switch methods. They can either take a State subclass instance as a parameter, or some sort of identifier. I think this choice is 50-50; I don't have a clear preference for either one.
There's two ways of doing identifiers. Again, I don't have a clear preference here either. I tend to switch back & forth between these two solutions. (1) Add an ID in the class itself, e.g.
public static const MainMenu::kMenuId = 'main';
This tends to be the less error-prone, although it does mean that you've got to add an extra #include (in C++), and whatever language you use it means another dependency. (2) Use a string constant. C++ compilers tend to tolerate four-character codes, ie Context.Switch( 'main' );
The downside is that if you change the identifiers or add a new menu or have a typo, you run the risk of the system blowing up at runtime. However you might choose to do the identifiers, you also need a way to register them with the Context, and that adds another layer of complexity. So your choice is: that complexity, or require any class that requests a menu state change to refer to the new menu class -- which can get messy itself. Meh? All coding is tradeoffs. Pick one. Whatever your feelings on Good and Proper Coding Practices, neither one has been proven to cause cancer in lab rats.The Context itself also tends to be an instance of the Singleton pattern, with some public, global access. Pop, Push, and Switch might be static methods, for example; I find that means less code and complexity on the client side. (Never trust anyone using your class to be able to code their way out of a paper bag! Simpler interfaces are better.)
I usually start with a simple, copy-n-pasted examples of the different Menu classes. For example, they'll have their own Scenes for 3D objects and 2D UI bits. This is usually easier, faster, and more reliable than trying to develop the Most Awesomest Generic Menu Class Ever. The UI manager will take button clicks, and then call Context.Switch() or Pop() as needed, or Push() if the user hits the 'previous menu' button.
Game startup, then, will do stuff like initialize the 3D environment, game asset libraries, sound, etc, then start up the game state context and tell it which State to start with, which is often a CompanyLogoState. Usually I have game startup then call Context.Run, which does a simple loop of CurrentState.HandlePendingEvents, CurrentState.Draw, and CurrentState.Tick. There's some complexity there with handling events, being able to handle Push and Pop, updating the state at the right time, etc.
CompanyLogoState.Tick() will usually draw a 2D company logo, gradually brightening from black to white, holding, then back to black. When it gets to black, Tick() will call Context.Switch( GameTitleState.kStateId ), which pops the CompanyLogo off the stack and puts GameTitle in its place. That state does the same thing -- bring up the lights, so the title screen, then switch to the Main Menu state. Both the CompanyLogo and GameTitle states will move on to the next state if a key is pressed; that's done in their HandlePendingEvents() method. Eventually, one of the various Menu states (MainMenu, PlayGameMenu, LoadSavedGameMenu / StartNewGameMenu, etc etc) will need to actually start the game. That's cake: just have it call Context.Push( GameState.kMenuId ). And if the game needs to switch to a full-screen menu at some point, it can pause itself and push a new state onto the stack: Context.Push( SaveGameMenu.kMenuId ). Of course it will be important to plan out all of your various menus and states, and make sure you don't have any recursive loops.
Using this pattern, all of the various high-level states in the game are handled through the Context, which also does event handling and rendering. I've even once modified the process to work in a nested window as well - such as when you bring up the 'game menu' while a game is in progress, which doesn't back out into a full-screen menu but instead shows the game in the background, paused & faded.
As with any code, start simple. Copy n paste as needed. When you need more complexity, well-written code is easy to extend.
Saturday, March 27, 2010
Repeat Until Rich
Repeat Until Rich
Labels:
gambling
Thursday, March 25, 2010
Adapter Pattern vs Proxy Pattern
These are two similar patterns that both wrap an object (or set of objects) to expose slightly different behavior to a client object. As with the difference between Bridge and Strategy patterns, the difference between an Adapter and a Proxy is partly one of focus; which pattern you use does not necessarily change the structure of your solution, but the choice depends on how you approach the problem. Both patterns are wrappers, but you use the two patterns for very different reasons.
Some of the confusion that I've seen between these two patterns is one of nomenclature. I was talking to a friend today (hence the reason for this post) where he got into an argument with someone, and the basic cause of confusion was between the idea of a class (any class) as a 'proxy' for a data object and the Proxy pattern itself. As for the Adapter pattern and the verb 'adapt' -- well, every line of code is an adaptation, right? It's a pretty generic verb.
So: Most of the confusion is proxy vs Proxy. I'm using the latter, the capitalization, to indicate the Design Pattern.
Adapter
Common descriptions of the Adapter pattern tend to say that it's an extension of the Facade pattern to deal with polymorphism or to provide a specific interface. Yeah, that's nice. In practice, when I'm getting my hands dirty writing code, I use the Adapter pattern when I am approaching the problem from the client end - as the user of the class that's about to be adapted, not as the author of the library or utility class that winds up getting adapted.
Usually what happens is that I'm writing a bit of code and I start to implement an algorithm when I realize that I can use a certain library class to do the job instead. But the class I'm working in demands a certain interface! Rather than rewriting the algorithm using that interface, I instead glue the library class in. And that, really, is all that an Adapter is: it's an implementation of an interface that doesn't do any of the work itself -- it just passes the calls along to some other, existing class.
It retrospect, you can see that you have Adapted the library class to the new interface.
Proxy
Proxies, on the other hand, tend to do work. Real work. Usually I create a proxy knowing exactly what it is that I want to do. I need a client-side representation of a server object, or a class to represent some big, unwieldy system object that I'm really only going to provide some minor methods on (and hence don't need to instantiate the whole thing). My proxy looks like the real object, but only provides the methods needed locally -- and so only has the complexity to do that limited work.
Often Proxies are one-to-one wrappers; you'll have two classes to represent the object. One class (the non-proxy, usually written first) represents the underlying data, and the Proxy wraps that class to add some specific, narrow behavior.
A proxy might exist across a network connection; it might represent a view into a data object, or a partial instance of a large data file, or maybe it just provides some functions that would be expensive or complex to access directly. I often write proxies to do one simple thing to a more complex class. Instead of making some class more complex, the Proxy steps in.
Which is Which?
In some cases the distinction is obvious. In a client-server application, you might write a client Proxy for a server-side object. You might gate calls to a complex central system through a Proxy, which will provide transaction ordering or synchronous behavior or somesuch. If you need to shove Tab A into Slot B and a simple pass-through class will do, that's an Adapter.
But say you want to write a class to encapsulate OS-level calls to the file system. Is that an Adapter or a Proxy? It's pretty simple, like a pass-through, so it's an Adapter, right? But an object of that class is treated like the underlying object, so is it a Proxy for the actual file on disk?
This is one of the cases where normal pattern use breaks down. Such a class is both a proxy and an adapter. A file object is a proxy for the actual file, but the class itself adapts the OS library calls to your custom project/application/module.
And so it doesn't really matter what you call it. The confusion comes because 'proxy' can be used to refer to the pattern itself (in which a class does work to hide complexity or extract specific behavior) or to an object that represents some real data object. One might say that every data-object instance in your application is a proxy. The concept of proxy still holds independent of the jargon that us OO design-pattern wonks use. Any class can be a proxy - even an Adapter class.
But note that you wouldn't normally have a Proxy that 'adapts' to anything. The Proxy pattern might 'adapt' something, but if the class you write is an Adapter, it might be a proxy but it won't be a Proxy.
As I said above, when I write an Adapter, I know it; the problem in front of me is fairly clear: "I need to shove this old/library class into this custom interface." And when I write a Proxy, it's clear that I'm providing specific new behavior.
Some of the confusion that I've seen between these two patterns is one of nomenclature. I was talking to a friend today (hence the reason for this post) where he got into an argument with someone, and the basic cause of confusion was between the idea of a class (any class) as a 'proxy' for a data object and the Proxy pattern itself. As for the Adapter pattern and the verb 'adapt' -- well, every line of code is an adaptation, right? It's a pretty generic verb.
So: Most of the confusion is proxy vs Proxy. I'm using the latter, the capitalization, to indicate the Design Pattern.
Adapter
Common descriptions of the Adapter pattern tend to say that it's an extension of the Facade pattern to deal with polymorphism or to provide a specific interface. Yeah, that's nice. In practice, when I'm getting my hands dirty writing code, I use the Adapter pattern when I am approaching the problem from the client end - as the user of the class that's about to be adapted, not as the author of the library or utility class that winds up getting adapted.
Usually what happens is that I'm writing a bit of code and I start to implement an algorithm when I realize that I can use a certain library class to do the job instead. But the class I'm working in demands a certain interface! Rather than rewriting the algorithm using that interface, I instead glue the library class in. And that, really, is all that an Adapter is: it's an implementation of an interface that doesn't do any of the work itself -- it just passes the calls along to some other, existing class.
It retrospect, you can see that you have Adapted the library class to the new interface.
Proxy
Proxies, on the other hand, tend to do work. Real work. Usually I create a proxy knowing exactly what it is that I want to do. I need a client-side representation of a server object, or a class to represent some big, unwieldy system object that I'm really only going to provide some minor methods on (and hence don't need to instantiate the whole thing). My proxy looks like the real object, but only provides the methods needed locally -- and so only has the complexity to do that limited work.
Often Proxies are one-to-one wrappers; you'll have two classes to represent the object. One class (the non-proxy, usually written first) represents the underlying data, and the Proxy wraps that class to add some specific, narrow behavior.
A proxy might exist across a network connection; it might represent a view into a data object, or a partial instance of a large data file, or maybe it just provides some functions that would be expensive or complex to access directly. I often write proxies to do one simple thing to a more complex class. Instead of making some class more complex, the Proxy steps in.
Which is Which?
In some cases the distinction is obvious. In a client-server application, you might write a client Proxy for a server-side object. You might gate calls to a complex central system through a Proxy, which will provide transaction ordering or synchronous behavior or somesuch. If you need to shove Tab A into Slot B and a simple pass-through class will do, that's an Adapter.
But say you want to write a class to encapsulate OS-level calls to the file system. Is that an Adapter or a Proxy? It's pretty simple, like a pass-through, so it's an Adapter, right? But an object of that class is treated like the underlying object, so is it a Proxy for the actual file on disk?
This is one of the cases where normal pattern use breaks down. Such a class is both a proxy and an adapter. A file object is a proxy for the actual file, but the class itself adapts the OS library calls to your custom project/application/module.
And so it doesn't really matter what you call it. The confusion comes because 'proxy' can be used to refer to the pattern itself (in which a class does work to hide complexity or extract specific behavior) or to an object that represents some real data object. One might say that every data-object instance in your application is a proxy. The concept of proxy still holds independent of the jargon that us OO design-pattern wonks use. Any class can be a proxy - even an Adapter class.
But note that you wouldn't normally have a Proxy that 'adapts' to anything. The Proxy pattern might 'adapt' something, but if the class you write is an Adapter, it might be a proxy but it won't be a Proxy.
As I said above, when I write an Adapter, I know it; the problem in front of me is fairly clear: "I need to shove this old/library class into this custom interface." And when I write a Proxy, it's clear that I'm providing specific new behavior.
Labels:
patterns
Tuesday, October 27, 2009
Loot and New Content
Back in the Olden Days, when we had to walk to school in the snow, uphill both ways, the only way to get awesome loot in WoW was to run Molten Core. If you didn't have 36+ friends that were all well-geared, attentive, and competent, your only chance at purples was world drops and auction housing. You could run UBRS or Strat or Scholo if you wanted to, but there wasn't really much reason; there were some nice pieces in there but gear in MC was far better. Yet you couldn't progress in MC but once a week, and you needed to be well-geared, attentive, and competent yourself.
Nowadays, loot is cake. All you need in 9 friends, and there's no trash to fight through so you don't even need a multi-hour commitment.
Better
Is the current system better? Well, what does 'better' mean? It's easier to get loot. You don't need the social structure now that was needed then. 10-mans are easier to organize than 40-mans, it's harder for a player to go AFK, it's easier to get into a guild that has 10 people that can raid on the same night at the same time, and more. The barrier to loot is lower, in that more people will be able to get this group together. Is that better?
You don't need to progress through MC then BWL then AQ20 to get to AQ40; now, run some heroics, build up some purples, then jump into a 10-man ToC group. Or, heck, some heroic 5-mans drop competitive purples. A new 10-man guild can move on to 10-man ToC fairly quickly, and then find a 25-man PUG. The time between hitting end-level and raiding the final dungeon is much lower. Is that better?
One of the reasons that initiation rituals remain in fraternities is that it makes admission to the group that much harder and stressful. We value that which was difficult to obtain. Downing Ragnaros was a serious effin task, especially before BWL was released. It was a badge of honor.
Where is that badge now? Is that relevant? Compared to 2005, nowadays many more people are seeing more content and improving their gear, without getting frustrated by organizational hurdles. Because more people get there, it's less exclusive.
Who Cares?
It doesn't seem to matter. If more people are getting more phat lewt, they're happier and having more fun. I might complain about more people reaching the "elite" end-game ranks -- but there's still a time factor. What distinguishes the top elite from the next group is when they achieved the rank, not if they got to that final boss.
I've talked to players doing 10-man normal ToC and they consider themselves up in the elite. They're very happy with their progression. They know they're not doing hard-mode, much less the 25-man version, but that doesn't seem to be a big deal. At least they're not stuck!
There were tons of players back in the first year of WoW that wanted to do MC, but couldn't, because they weren't in "the right guild." Even in that guild some players got left on the sidelines because their gear wasn't good enough. Now, those guys have somewhere to go. They're not stuck pugging MC and wiping on the first giant; they can do 5-man and 10-man content that continues to give them better loot.
Bias
I want to sit and bitch about how easy kids have it these days, but that just biases me against the current model. What makes a game fun is perceived mastery, and WoW has that.
The WoW end-game is loot acquisition, and as long as players are getting better loot, they are mastering the game.
Lessons
Progression is important. Really, that's it. Players like challenge but not because of the cost of failure. They want to succeed, and look back, and say "I overcame that." As long as players continue to progress, they'll have fun, be happy, and continue to pay.
Nowadays, loot is cake. All you need in 9 friends, and there's no trash to fight through so you don't even need a multi-hour commitment.
Better
Is the current system better? Well, what does 'better' mean? It's easier to get loot. You don't need the social structure now that was needed then. 10-mans are easier to organize than 40-mans, it's harder for a player to go AFK, it's easier to get into a guild that has 10 people that can raid on the same night at the same time, and more. The barrier to loot is lower, in that more people will be able to get this group together. Is that better?
You don't need to progress through MC then BWL then AQ20 to get to AQ40; now, run some heroics, build up some purples, then jump into a 10-man ToC group. Or, heck, some heroic 5-mans drop competitive purples. A new 10-man guild can move on to 10-man ToC fairly quickly, and then find a 25-man PUG. The time between hitting end-level and raiding the final dungeon is much lower. Is that better?
One of the reasons that initiation rituals remain in fraternities is that it makes admission to the group that much harder and stressful. We value that which was difficult to obtain. Downing Ragnaros was a serious effin task, especially before BWL was released. It was a badge of honor.
Where is that badge now? Is that relevant? Compared to 2005, nowadays many more people are seeing more content and improving their gear, without getting frustrated by organizational hurdles. Because more people get there, it's less exclusive.
Who Cares?
It doesn't seem to matter. If more people are getting more phat lewt, they're happier and having more fun. I might complain about more people reaching the "elite" end-game ranks -- but there's still a time factor. What distinguishes the top elite from the next group is when they achieved the rank, not if they got to that final boss.
I've talked to players doing 10-man normal ToC and they consider themselves up in the elite. They're very happy with their progression. They know they're not doing hard-mode, much less the 25-man version, but that doesn't seem to be a big deal. At least they're not stuck!
There were tons of players back in the first year of WoW that wanted to do MC, but couldn't, because they weren't in "the right guild." Even in that guild some players got left on the sidelines because their gear wasn't good enough. Now, those guys have somewhere to go. They're not stuck pugging MC and wiping on the first giant; they can do 5-man and 10-man content that continues to give them better loot.
Bias
I want to sit and bitch about how easy kids have it these days, but that just biases me against the current model. What makes a game fun is perceived mastery, and WoW has that.
The WoW end-game is loot acquisition, and as long as players are getting better loot, they are mastering the game.
Lessons
Progression is important. Really, that's it. Players like challenge but not because of the cost of failure. They want to succeed, and look back, and say "I overcame that." As long as players continue to progress, they'll have fun, be happy, and continue to pay.
Wednesday, October 14, 2009
Creating an Engine from Scratch
I've been coding since I was ten. That's nearly thirty years now. In that time I've worked on games ranging from simple Apple II fare to big-budget PC and console titles. I've also written a ton of applications and tools, on the PC and Mac and that old Apple II, too.
So I can create an engine from scratch if I want to. Do I want to?
Right now, the 2D RPG I'm working on is an XNA title. I'm not using an engine, tho I am using the XNA and .NET libraries. Coding up my own engine is not too bad, but there's still tons of little cruft that I have to code. I wrote a line-wrapping routine last night; the code that breaks up a string of text across multiple lines. It's perhaps the tenth time I've written such a routine.
It's the sort of thing that makes me wish I had used an engine, something that would give me those sorts of routines. I know how to write them and I've got old code laying about that I can crib from, but I still need to modify the code for the language (C#) and platform (XNA) du jour.
The downside to using an engine is learning it. I remember old Mac documentation, back in the pre-OS X eras. It was awesome. It took a long time to read (compared to today's documentation), but it was fucking stellar. Not just explanations of parameter values, but meaningful sample code (including error-checking) for nearly every use that a particular function had.
Today, most of the documentation and comments I see are like:
Engines are also often buggy; if you don't have source, you're just screwed. Wait six months for the next update and hope it fixes your problem. And being generic engines, they have a strange mix of too-much and too-little functionality. They don't do exactly what you want, but they can do a dozen things that are similar but still inappropriate for your specific needs. So it takes you days to figure out what it does, and then days trying to make it dance the way you need it to -- only to find out it doesn't do that. Then days more to figure out how to change your game spec so that your requirements can be met by the subset of functionality that the engine actually provides.
Using an engine is a great idea if it would take you too long to write it yourself, and if you can amortize the learning time across multiple projects (ie reusing the engine). Finding a great, easy-to-use, powerful, flexible, well-documented, and robust engine is a pain in the ass. Plus, generally impossible. There just aren't enough engines out there (and they're not profitable enough to develop) for them to be stellar products.
The big engines these days are cross-platform; PC, XBox, PS3, and Wii. There's some smaller engines that enjoy some niches, but I don't have high hopes for their lifetimes. Those big cross-platform engines can meet some of those important feature points, but (back when I was seriously looking at them, at game-industry day jobs) they weren't 100%. There's some smaller engines that have a lot of promise, too -- yet they're very niche.
Niche is good. If it does just what you need it to, a niche engine can be great. You don't waste time and money on features you won't use, and it's more likely that the engine does exactly what you need, does it well, and can document its small feature set well. Here, I'm thinking about engines for the iPhone, or 3D-shooter-specific engines, etc.
Which brings me back to that first point: if you lack the experience and talent to quickly develop an engine yourself, chances are, using a cumbersome, weak, inflexible, poorly-documented, and buggy engine will be your best choice. This is mostly cuz of the arcana associated with a new platform and the toolchain that goes with it. An engine isn't just line-wrapping code; it's a sound system, 3D rendering and scene graphs, advanced shaders, exporters for Max and Maya, input abstractions, UI widgets, plus tons more. Maybe even a scripting language and enough of a game shell that most of what you need to do is plug in some art assets, do a bit of scripting, and ship your product. If I was developing an XBLA or a PS3 or even a AAA PC title, I'd be using an engine.
There's a time balance between learning someone else's engine and writing the code you need yourself. The smaller the requirements you have for the engine, the more it makes sense to do it yourself. That's one reason why I'm writing my own engine. Plus, I get to reuse this engine for the next title I do. Plus, I'm not stuck with broken code. Plus, the engine does exactly what I need it to do.
It's still annoying to have to write line-wrapping code. Again.
So I can create an engine from scratch if I want to. Do I want to?
Right now, the 2D RPG I'm working on is an XNA title. I'm not using an engine, tho I am using the XNA and .NET libraries. Coding up my own engine is not too bad, but there's still tons of little cruft that I have to code. I wrote a line-wrapping routine last night; the code that breaks up a string of text across multiple lines. It's perhaps the tenth time I've written such a routine.
It's the sort of thing that makes me wish I had used an engine, something that would give me those sorts of routines. I know how to write them and I've got old code laying about that I can crib from, but I still need to modify the code for the language (C#) and platform (XNA) du jour.
The downside to using an engine is learning it. I remember old Mac documentation, back in the pre-OS X eras. It was awesome. It took a long time to read (compared to today's documentation), but it was fucking stellar. Not just explanations of parameter values, but meaningful sample code (including error-checking) for nearly every use that a particular function had.
Today, most of the documentation and comments I see are like:
int key; // the keywtf? That comment is noise. It's a waste of space and the time it takes me to look at that and then realize it contributes NOTHING.
Engines are also often buggy; if you don't have source, you're just screwed. Wait six months for the next update and hope it fixes your problem. And being generic engines, they have a strange mix of too-much and too-little functionality. They don't do exactly what you want, but they can do a dozen things that are similar but still inappropriate for your specific needs. So it takes you days to figure out what it does, and then days trying to make it dance the way you need it to -- only to find out it doesn't do that. Then days more to figure out how to change your game spec so that your requirements can be met by the subset of functionality that the engine actually provides.
Using an engine is a great idea if it would take you too long to write it yourself, and if you can amortize the learning time across multiple projects (ie reusing the engine). Finding a great, easy-to-use, powerful, flexible, well-documented, and robust engine is a pain in the ass. Plus, generally impossible. There just aren't enough engines out there (and they're not profitable enough to develop) for them to be stellar products.
The big engines these days are cross-platform; PC, XBox, PS3, and Wii. There's some smaller engines that enjoy some niches, but I don't have high hopes for their lifetimes. Those big cross-platform engines can meet some of those important feature points, but (back when I was seriously looking at them, at game-industry day jobs) they weren't 100%. There's some smaller engines that have a lot of promise, too -- yet they're very niche.
Niche is good. If it does just what you need it to, a niche engine can be great. You don't waste time and money on features you won't use, and it's more likely that the engine does exactly what you need, does it well, and can document its small feature set well. Here, I'm thinking about engines for the iPhone, or 3D-shooter-specific engines, etc.
Which brings me back to that first point: if you lack the experience and talent to quickly develop an engine yourself, chances are, using a cumbersome, weak, inflexible, poorly-documented, and buggy engine will be your best choice. This is mostly cuz of the arcana associated with a new platform and the toolchain that goes with it. An engine isn't just line-wrapping code; it's a sound system, 3D rendering and scene graphs, advanced shaders, exporters for Max and Maya, input abstractions, UI widgets, plus tons more. Maybe even a scripting language and enough of a game shell that most of what you need to do is plug in some art assets, do a bit of scripting, and ship your product. If I was developing an XBLA or a PS3 or even a AAA PC title, I'd be using an engine.
There's a time balance between learning someone else's engine and writing the code you need yourself. The smaller the requirements you have for the engine, the more it makes sense to do it yourself. That's one reason why I'm writing my own engine. Plus, I get to reuse this engine for the next title I do. Plus, I'm not stuck with broken code. Plus, the engine does exactly what I need it to do.
It's still annoying to have to write line-wrapping code. Again.
Labels:
game engines
Subscribe to:
Posts (Atom)
