Bay 12 Games Forum

Please login or register.

Login with username, password and session length
Advanced search  
Pages: [1] 2 3 ... 8

Author Topic: Let's Make! (Dathida's Legacy, a graphical roguelike)  (Read 12746 times)

Lemunde

  • Bay Watcher
    • View Profile
Let's Make! (Dathida's Legacy, a graphical roguelike)
« on: June 29, 2010, 03:31:39 pm »

View the blog at http://dathida.blogspot.com/

Ground Rules:
*First understand that despite the thread's name I am really the only person working on this game.  As such I will be making design decisions that not everyone will agree with.
*Constructive criticism is accepted. However any criticism that is insulting, vague or contains any phrase similar to "you're doing it wrong" will be considered nonconstructive and will be reported.  If you think your post may be nonconstructive, play it safe and don't post.
*While I will try to be as forthcoming as possible, I cannot explain everything I'm doing or the reasons I'm doing them.  Some questions may go unanswered but this is not to offend the poster.
*Stick to the forum rules and please avoid derailing this thread.  I may have to end certain kinds of discussions before they get out of hand.  If I say a discussion is over, it's over.
*If you have any problems with any of these rules, please don't post.

---------------------------------------------------

I posted this on another forum but that one moves so fast it's unlikely anyone will pay much attention to it.

I've been debating on whether or not to start this thread for several reasons. First of all let me try to explain what I'm trying to accomplish here.

I've been developing this game in my mind for quite some time. I've also made several attempts to program an engine for it but I usually quit out of frustration or lose interest. It's not that the game concept isn't interesting but after I spend several days working on it I start to lose focus and my attention ends up on something else. This is a common problem for me. I actually have several games I've been working on on the back burner and I've only actually managed to finish one of them.

So what I thought I might try is making a thread to try to gather my thoughts. This way if I start to lose focus again I'll atleast have all my thoughts recorded somewhere so I can come back to it later. Think of this as one of those "let's play" threads except instead of playing a game I'll be making one. It is my hope that would-be developers will see this and get some understanding in what all goes into making a game. Also understand that my method isn't THE method as there are many ways to go about making a game from scratch. And any comments or suggestions will be greatly appreciated.

---------------------------------------------------

Okay, so I'll start by describing what the game is, the current state the game is in and what my goals are. The game is a graphical roguelike. The current working name is Roguelike 7. The 7 represents the actual number of times I've started over from scratch. It's not that there was anything wrong with the previous incarnations but I kept coming up with ideas that would make developing it easier or scratching ideas that were much too complicated and didn't really mesh with what I was trying to accomplish.

So this is my 7th attempt. I am programming it in C# using Microsoft XNA. It uses a system similar to Eschalon for the overall flow. That is, it is entirely turn based but animates between turns. Currently it uses a purely top-down perspective but this may change. The sprites for the characters are pseudo-ascii but this may also change if I can figure out an easy way to make artwork for them. The map tiles are all bitmaps.

The gameplay is a little different from your typical roguelike. The basics are all there; search the world for treasure and glory while fending off goblins and liches using swords and sorcery. The differences come in the mechanics.

First of all you do not gain levels like in other RPGs. Character advancement comes through completing quests, finding certain kinds of loot and training under a teacher. Here's a scenario that might better explain how it works.

You're wandering through the woods and you come across the home of a necromancer. You find that the necromancer isn't really hostile to you so rather than attack him you speak to him. Through the conversation you discover that he is willing to tutor you in the arts of necromancy. Of course everything comes with a price. As part of your training and to assist with his own studies, he sends you on a quest to find a corpse and bring it back to him. He isn't very particular about where or how you obtain one as long as it is humanoid and dead. When you return with a corpse he teaches you a basic spell to resurrect a small creature as an undead servant. Further tasks you sends you on become progressively much more difficult. Besides spells, your mana may increase slightly with each training quest. When he has taught you all he knows he will send off to a more powerful necromancer to further your training. If he were a mage training you in magic he might send you off to a special school for magicians instead.

As you can imagine, this is a much better way to get the player involved with the world rather than running around hacking on enemies for experience points. However if you do want to hack up some goblins it may be a great way to earn some cash. The local sheriff may pay you handsomely for goblin heads.

The world itself will be very dynamic and, being a roguelike, it will be randomly generated each time you start a new game. Features found in one game may be completely different from features found in another. One world may not even generate any necromancers willing to train you, but if you search far and wide you might find a hidden assassin's guild who will welcome you under the right circumstances.

The use of magic is a little different. In most RPGs you use some kind of mana or MP to cast your spells. Actually I think this is a perfectly acceptable way to handle magic. But I want to take it a step further. Borrowing from one of my favorite card games, instead of having one source of mana you may have several. I haven't decided on the exact number yet but I'm thinking somewhere between 4 and 7. If you have played MTG this will sound familiar. Let's say you do want to cast one of those raise undead spells. Well in order to cast it you will need to have enough dark mana to do it. Let's say you were training under a priest for a long time before you decided to go necromancer. In that case you may have a whole lot of holy mana but almost no dark mana as training under the priest would have depleted your dark mana in favor of holy mana. As far as mana goes, you would have to train longer with the necromancer just to have your dark mana back where it started. But your holy mana will decrease as well. In the interest of progression I may make it a 2/1 trade off; you gain 2 parts from one mana type but lose 1 part from another.

Of course not all spells will require the use of just one mana source. You may learn some kind of holy fire spell that will require the use of both holy and elemental mana.

Well that's the gist of the major features. There's a lot more but it's not too different from what you've seen in other games. I'm still working on the basic engine so it will be some time before I decide how to work all these features in. I got a guy I'm controlling walking around on the screen, bumping into randomly generated walls and I got a goblin following me around. Not a bad start but there is so much more to do before I can get to the fun stuff. I think the next thing I have to do is add some form of simple combat. Gotta get that goblin to swing a sword at me and do damage. My next post may be pretty technical so be prepared.

---------------------------------------------------

Detailed description (subject to change)

Player character: The player starts off roughly the same way every game, with only a rudimentary set of skills.  The player will have the option to change their race and attributes but there are no specific classes, at least not at the beginning of the game.  Through training the player may be granted certain titles and in combination with the training they receive this will fill the role of classes found in other games.

Skills and/or commands the player will start with may include:
*Basic weapon skills(slash, stab, bash)
*Fire starting
*Cooking
*Foraging
*Throwing
*Basic crafting
*Basic forestry for moving and seeing in forests
*Basic swimming

Training in slightly more advanced skills such as basic magic use will be available close to the start of the game and will make for good starting quests.

Advanced skills and/or commands include:
*Sneaking
*Ranged weapon use
*Armor/weapon crafting
*School specific magic use
*Golem creation(requires magic + armor set)
*Necromancy(requires magic + corpse parts)

Map features: Maps will feature forests, lakes, rivers, roads and rocky areas as well as minor features that occupy individual tiles such as cacti, boulders and shrubs.  Towns and villages will have houses, shops and inns made from wood, stone and other materials.  Roads will be appropriately generated in towns and villages and walls will be generated around larger cities.

Forests will provide several functions based on the player's forestry skill.  A high forestry skill will allow players and creatures to see further and move faster in forests.  A player with a low sneak skill but a high forestry skill may be able to hide in a forest to ambush other creatures or they can duck into a forest to lose their pursuers.

Lakes and rivers will provide similar functions for player's with a swimming skill.  In addition, elemental spells with a cold effect will freeze creatures in place that are swimming in the affected tile and the frozen tile will provide a temporary bridge.

Caves will appear on some maps.  These will have multiple levels and will have a variety of layouts.  I haven't worked out the particulars of how these will be generated or what varieties they will come in yet.

Other types of dungeons the player may find will include towers and fortresses.  Fortresses will be home to potential overlords and towers may house powerful sorcerers or even the dreaded lich.  The player may also come across villages or hideouts of hostile creatures such as goblins and bandits.

A village may periodically be attacked by local bandits or goblins and the player will be rewarded for helping in the defense.

Lore: With many features being generated randomly, much of the lore will not directly relate to current events.  The purpose of the lore will be to give the player some idea of the history and nature of certain elements.  For instance there will be detailed information on goblin culture but little to no information on their current conflicts.

Gods: Most of the major gods will be permanently fixed into the lore.  Minor gods will be generated randomly.  Minor gods will include world dwelling demigods, false gods and powerful creatures worshipped as gods such as dragons.  Appropriate text will be added to conversations when asked about their religion.

Dathida will be the first among the major gods.  Dathida is the god credited with the creation of the world and is associated with chaos and disarray.  It is believed that every hundred thousand years Dathida destroys the world and creates a new world.  It is for this reason that most cultures choose not to worship her.  However she does have a devout following of cultists known as The Arbiters of Chaos.  Prayers to Dathida, if answered, have unpredictable results.

Other gods have taken it upon themselves to influence the world in their own ways.  This counteracts Dathida's chaotic nature and gives the world a semblance of order.  The forces of order, chaos, good and evil are always at odds with eachother and no one side has ever maintained an advantage for very long.

Creatures:

Goblins: Goblins are savage, tribal creatures that tend to inhabit forests.  They dwell in small villages made up of straw huts.  They have no tolerance for outsiders and usually attack on sight.  Most goblins wield simple weapons made of wood or iron.

Goblins tend to worship false gods.  It is not uncommon for one tribe to worship a completely different god than another.  Goblin priests train themselves in rudamentary magic to try to emphasize their god's power.  Unlike the priests of civilized cultures, goblin priests do not focus on holy magic but tend towards dark and elemental magic.

Physically goblins are fairly weak, relying on large numbers to take down their enemies.  They have moderate knowledge of forestry and sometimes resort to stealthy ambushes to attack invaders.

Skeletons, Necromancers and Liches: Many creatures are cursed to have their remains reanimated by a necromancer.  Novice necromancers often make the mistake of trying to reanimate a decaying corpse but this results in a creature that is so encumbered by it's own flesh that it is generally useful only as a decoy when a priest catches the foolish necromancer pilfering their cemetary. 

A seasoned necromancer will either remove the bones from the corpse manually or use a fire spell to burn the flesh away before animating it.  Either way, necromancers are required to devote a certain amount of their dark mana to the corpse while it is animated.

A skeleton's physical strength is comparable to it's living counterpart.  What makes skeletons so formidable is their resistance to most weapons along with dark and elemental damage.  Their speed is also somewhat higher.

Unlike a decaying corpse, a skeleton has none of the drawbacks of mortal flesh.  Slashing and piercing weapons such as swords and spears have little effect on skeletons but bashing weapons such as maces and hammers are excellent at smashing and scattering the bones which is enough to dispel the sorcery that holds them together.

Necromancers often use skeletons to defend their homes or perform menial tasks.  Skeletons found wandering the wilderness or inside dungeons are usually not the work of a necromancer, but a lich.

A lich is an animated necromancer and is the ultimate form that most necromancers strive for.  Unlike skeletons, a lich retains it's identity through the use of an artifact that holds it's soul.  And unlike a necromancer, a lich is powerful enough to maintain dozens of skeletons at a time.  A lich has no fear of death as long as it retains it's artifact.  It will strike without provocation and without mercy.  Only through the destruction of the artifact can you permanently kill a lich.  However some powerful sorcerers and overlords have enthralled a lich by taking it's artifact and keeping it for themselves.

--Gameplay Note: Skeleton and Zombie will be a subclass of a creature much like Thief and Sorcerer and will replace any of these classes.  Attributes will remain the same other than increased speed and resistance to slashing, piercing, dark and elemental magic. On a related note, there may also be a possibility that after the player dies the game will continue.


Still more to come...
« Last Edit: July 07, 2010, 10:45:22 am by Lemunde »
Logged

SolarShado

  • Bay Watcher
  • Psi-Blade => Your Back
    • View Profile
Re: Let's Make! (Like a "Let's Play" but making a roguelike instead)
« Reply #1 on: June 29, 2010, 04:05:21 pm »

Sounds cool. I'll be keeping an eye on this for sure, and I'll try to contribute advice when I can.
Logged
Avid (rabid?) Linux user. Preferred flavor: Arch

ILikePie

  • Bay Watcher
  • Call me Ron
    • View Profile
Re: Let's Make! (Like a "Let's Play" but making a roguelike instead)
« Reply #2 on: June 29, 2010, 04:56:53 pm »

I just gave your essay a quick read, I like the idea, and I'd happily contribute. I've using C# on and off for about a year now, but I've recently had the urge to learn something more complex, like C.

I have to ask though, why use C#? Unless you're planning on this running on a 360, I see no point in using XNA or C# when you can use something as compatible and fast as C with ncurses.
Logged

Lemunde

  • Bay Watcher
    • View Profile
Re: Let's Make! (Like a "Let's Play" but making a roguelike instead)
« Reply #3 on: June 29, 2010, 05:33:53 pm »

I just gave your essay a quick read, I like the idea, and I'd happily contribute. I've using C# on and off for about a year now, but I've recently had the urge to learn something more complex, like C.

I have to ask though, why use C#? Unless you're planning on this running on a 360, I see no point in using XNA or C# when you can use something as compatible and fast as C with ncurses.

Everyone has their own environment that they like to use and I've heard all the arguments over why x language is better than y language.  In short, this is what I'm used to and I'm not about to start over learning another language or I'll never get done.  Actually if I were to use anything else it would be rapid euphoria but that would probably weird you out even more.
Logged

Blacken

  • Bay Watcher
  • Orange Polar Bear
    • View Profile
Re: Let's Make! (Like a "Let's Play" but making a roguelike instead)
« Reply #4 on: June 29, 2010, 05:35:47 pm »

XNA is an excellent choice for this sort of project (Sharplike would use it if I didn't have a graphics wiz on tap, as he's done the OpenTK magic). I'll be interested to see your results.
Logged
"There's vermin fish, which fisherdwarves catch, and animal fish, which catch fisherdwarves." - Flame11235

Urist McOverlord

  • Bay Watcher
  • [Evil_Genius]
    • View Profile
Re: Let's Make! (Like a "Let's Play" but making a roguelike instead)
« Reply #5 on: June 29, 2010, 05:43:25 pm »

This idea interests me.
I probably won't be able to contribute much, as my programming knowledge is somewhat nonexistent, but I will be rooting for you!
Logged
Magma: The cause of, and solution to, all life's problems.

If it moves, it wants to kill you. It may not try to, but it wants to.

Lemunde

  • Bay Watcher
    • View Profile
Re: Let's Make! (Like a "Let's Play" but making a roguelike instead)
« Reply #6 on: June 29, 2010, 07:04:21 pm »

Okay, I'm starting on the action stuff now.  Before I get that goblin swinging a sword I'm going to have to add some sort of action function that can handle a variety of tasks.

Let me back up a bit and explain some of the classes I have.  If you don't know much about programming, classes are simply big data holders that have certain user defined variables.  In it's current state the program has 3 main classes. 

*There's the Map class which contains all the information about the map
*There's the Tile class which contains all the information about tiles from the tileset (walltile, flootile, etc..)
*And there's the Creature class which has stuff like a creature's location, health, graphics, name, etc..

Further on in development I'll have to add classes for items, containers, spells and a few other things that I can't think of at the moment.  But right now let's talk about Creatures.  Pretty much everything that walks, flies or generally moves in a lifelike manner is a Creature.  This includes the player, NPCs, monsters...everything.  If there were a robot in this game it would be a Creature.  This is just for data organization and is not what they will be referred to in game.

Now in order to handle several Creatures at a time I had to create an array that I call CreatureList that contains all the information for all the creatures currently active.  Every frame I run a loop that goes through that list and updates the Creatures. Actually in this particular instance I don't necessarily update the Creatures every frame.  Since this is a turn based game I only have to update them every round or when they're animating.  The AI in particular only updates once every round.  Later I run another loop that draws them.

Okay, now where was I?  Actions!  I may be doing some thinking outloud here so bare with me.  I may need to create a new class for this because there are going to be a lot of actions.  But they're going to be so completely different that a class may not work.  Okay, here's what I'll do.

I'll add a string to the Creature class called sAction.  Oh, by the way I follow a certain naming convention for some of my variables to make them easier to work with.  All strings start with s, all ints start with i, all floats start with f and all vectors start with v.  The vector data type isn't normally found in other languages.  Just think of it as a variable that has an x position and a y position.  That's mostly all I use them for although they do have other uses.

So with sAction I can assign something like "Walk South" and on the next round the creature will move southwards.  If I assign something like "Attack Target" they will attack the creature that is stored in their target variable.  I may need to be more specific than that because there are many ways you can attack a target.  Or I could just let the AI figure it out on it's own.  It's still early enough to go either way.

But before I do any of that I'll have to design some kind of action to test it with.  I already have movement but I want something more interesting first.  I'll try designing a sword attack action.  I'll test it with the player first then I'll set up something in the AI to do it.  This will take some time as I'll need to make a new bitmap for weapons, draw a sword then figure out how I want the game to draw it.  And I'll need to do all that before I even start on the sword attack code.

I hope most of this made sense.  I tried to make it as straight forward as possible but I feel like I'm trying to explain color to the color blind.  Even to other programmers, explaining your own code isn't very easy.
Logged

Blacken

  • Bay Watcher
  • Orange Polar Bear
    • View Profile
Re: Let's Make! (Like a "Let's Play" but making a roguelike instead)
« Reply #7 on: June 29, 2010, 07:35:34 pm »

Some slightly disjointed notes:

I think your object model is insufficiently generic and you may not yet have a good grasp of your future requirements (for example, items - which are not fundamentally all that different from a mobile when you think about it; nor are containers, which are just items as well). Not trying to plug my own code, but you might do well to look at how we've implemented most of this stuff in Sharplike (swapping our Square class for your Tile class). The guys behind Sharplike (me, Total_Meltdown, and karantza) have built full game engines before and have taken into account things you likely have not yet run into; you can learn from it. Even if you don't look at Sharplike, you really will benefit from having your entire object model plotted out, including interfaces and abstract classes, before you start trying to hack away.

Arrays in .NET are not significantly faster than a List<T>; the list has an amortized O(1) for resizing (O(n) whenever you need to do it, amortized over the length of the data list) but so does the array class. If there's even the slightest chance of needing to grow larger (like the list of entities in a tile, or the entities contained within another entity--i.e., a box), then you should be using a List<T> instead of an array. When properly developing .NET code, the use of an actual "array" is extremely rare and should be avoided unless you know exactly why you want it. (For example, it's arguably shit that String.Split returns a String[]; it should return IList<String>, which is more flexible and more abstract.)

Similarly, your AI model seems rather crude. Why are you not just performing "thinking" in-order based on initiative/sequence or whatever and acting at the same time as the decision? Not doing it that way can result in out-of-order/old-data decisions that don't make internally consistent sense. Even if you decide to do early decision making, why are you using a string to store the data? You have a strong typing system in C# and .NET. If you're not using that typing system you might as well be writing C++ or something, you're giving up one of the strongest reasons to use .NET in the first place.

And seriously, for the love of god, nobody should use Hungarian notation (beginning variable identifiers with type indicators--this is what your IDE is for, use it). .NET code standards indicate not to do this. If you don't have a good reason to ignore those code standards (and I can't for the life of me think of one), you should not do so. Follow the standards that everyone else uses unless you have a good reason not to.
« Last Edit: June 30, 2010, 02:07:45 am by Blacken »
Logged
"There's vermin fish, which fisherdwarves catch, and animal fish, which catch fisherdwarves." - Flame11235

Lemunde

  • Bay Watcher
    • View Profile
Re: Let's Make! (Like a "Let's Play" but making a roguelike instead)
« Reply #8 on: June 29, 2010, 08:39:09 pm »

Heh, well I can't say I'm surprised my design technique could rub somebody the wrong way.  But trust me, it works.  Xeno Arena had a similar design and it ran silky smooth.

As far as the object model, items and containers, at least the way I have them figured, will have significantly different types of data than Creatures.  I may be able to get away with combining containers and Creatures but items are out of the question.  We'll see how it works out.  None of this is set in stone and everything is subject to change.  You are quite correct about using the string instead of something like an enumerator.  I was perhaps oversimplifying things and I probably won't use a string in the actual code. 

I don't quite understand what your problem is with Hungarian notation.  It keeps me in check and I often use the same words for different data types.  For example fSpeed and vSpeed.  They kind of mean the same thing but they're used in different ways and I definitely don't want to get them confused.  At any rate I don't plan on letting anyone else work on the code in the foreseeable future so I'll just leave it as is.

With the AI, well...it's a little difficult to explain but let's just say for what I'm doing it works better this way and leave it at that.  As I said before this is just one of a million ways to go about making a game.  I would never dream of demanding that everyone should use this technique to make their own games.  You should do what works best for you.
Logged

Total_Meltdown

  • Bay Watcher
  • BEEEEEEEES!!!
    • View Profile
    • Blogus Arbitrarius
Re: Let's Make! (Like a "Let's Play" but making a roguelike instead)
« Reply #9 on: June 29, 2010, 09:03:58 pm »

As far as the object model, items and containers, at least the way I have them figured, will have significantly different types of data than Creatures.  I may be able to get away with combining containers and Creatures but items are out of the question.  We'll see how it works out.  None of this is set in stone and everything is subject to change.  You are quite correct about using the string instead of something like an enumerator.  I was perhaps oversimplifying things and I probably won't use a string in the actual code.

Before you get started on a big project like this I would highly recommend familiarizing yourself with object-oriented design concepts, specifically inheritance, interfaces, and polymorphism. (By "familiarize" I really mean "read until you understand everything".) Get in the habit of making things as generic as possible. Creatures and items are conceptually different to the end user, yes, but they can both exist on the map, which makes them a good candidate for a common base class, equivalent to our entity class. Then you can take advantage of polymorphism and re-use a lot of code in your map class, which I suppose would be handling the placement of things in the world.

If you didn't follow what I just said, or don't understand why it's useful, you have a lot of reading to do.

I don't quite understand what your problem is with Hungarian notation.  It keeps me in check and I often use the same words for different data types.  For example fSpeed and vSpeed.  They kind of mean the same thing but they're used in different ways and I definitely don't want to get them confused.  At any rate I don't plan on letting anyone else work on the code in the foreseeable future so I'll just leave it as is.

Personally I'm with Blacken. Keeping track of datatypes for variables is not hard, and the compiler will catch any mistakes you make. Those prefixes make code a maintenance hassle (what happens if you decide that rather than storing a float for a radius, you'd rather use a vector to store an ellipse? Now you have to change your prefixes.)

That said, if that's what you want your project to be, it's your call really.

With the AI, well...it's a little difficult to explain but let's just say for what I'm doing it works better this way and leave it at that.  As I said before this is just one of a million ways to go about making a game.  I would never dream of demanding that everyone should use this technique to make their own games.  You should do what works best for you.

If you say so.

(P.S. No seriously, polymorphism is your friend. It's probably the most powerful tool you have in an object-oriented language like C#.)
« Last Edit: June 29, 2010, 09:07:45 pm by Total_Meltdown »
Logged

Blacken

  • Bay Watcher
  • Orange Polar Bear
    • View Profile
Re: Let's Make! (Like a "Let's Play" but making a roguelike instead)
« Reply #10 on: June 29, 2010, 09:11:45 pm »

Heh, well I can't say I'm surprised my design technique could rub somebody the wrong way.  But trust me, it works.  Xeno Arena had a similar design and it ran silky smooth.
Regardless of however you structure it, it can "run" smoothly. That doesn't make it a good design. It means it is functional. Functional is many steps below "good," because a "functional" design can still require disgustingly more work, and introduce many more logic errors, than a well-designed application will.

Brute force programming can work. It will not work optimally.

Quote
As far as the object model, items and containers, at least the way I have them figured, will have significantly different types of data than Creatures.
Which is why you subclass Entity as necessary. Polymorphism is your friend.

Quote
I may be able to get away with combining containers and Creatures but items are out of the question
Why? Items and creatures are, at their core, the same thing. That one moves around doesn't change things significantly. You polymorphically determine behaviors of the subclasses.

I would echo Total_Meltdown above: it seems that you don't have a good grasp of interfaces, inheritance, and polymorphism. Which isn't a failing on your part, don't get me wrong, it just means you haven't been educated on the topic. I would strongly suggest you spend some time reading up on polymorphism and inheritance, and why they're awesome. I hate to sound like a broken record, but Sharplike is probably a fairly good, accessible, easily understandable demonstration of interfaces, inheritance, and polymorphism that you can follow if you need an example. Also, both Meltdown and I (along with a bunch of other people) hang out in #bay12prog on irc.newnet.net (where #bay12games is, too) if you'd like to discuss this in real-time.

Quote
I don't quite understand what your problem is with Hungarian notation.  It keeps me in check and I often use the same words for different data types.  For example fSpeed and vSpeed.
This is not good design. It does not map to a sane problem set. In part I think it may be because you don't understand your problem domain well; there's no such thing as a "speed vector." A vector would be a measure of velocity, not speed. If you properly understand your problem domain, you will implicitly know when working with your code that speed, which is a scalar, will be measured as a floating-point variable. You will implicitly know that velocity is non-scalar.

Hungarian notation sucks because it is both inconsistent and utterly redundant. It tells you nothing that you do not already know. It makes refactoring your code later much more difficult (if you change a float to a double, you will be hunting for bad identifiers). It introduces stylistic inconsistencies between your code and .NET, which result in code that is anything but seamless. Hungarian is also often misleading, depending on what variables are being used. For example: in XNA you use the Vector class both to define locations--the equivalent of System.Drawing.Point--as well as velocity; the data type does not matter but its usage does. Nobody cares that it's a "vector", they care what it represents.

And, from a practical standpoint, you will have vastly too many classes to actually use Hungarian notation for them! Does "v" mean Vector2? Vector3 (surely you're using ortho projection in order to give yourself a nice easy hardware-accelerated Z-order, right?)? Vector4? Does it mean something out of XNA's PackedVector namespace, or just standard vectors? If you're following what I'm saying here, it should be evident that "v" is nowhere near specific enough to tell you anything meaningful. If you can't immediately tell that something is a vector from its identifier without the "v", is the "v" going to tell you if it's a Vector2 or Vector3? If it doesn't, you're going to need to mouseover the identifier so Visual Studio can tell you the type--which you would do anyway if the identifier lacked the "v" and you weren't sure of its type. If the identifier does tell you enough to immediately realize what data type it is, then you'll know it without the "v" and it is extraneous.

Hungarian is doubly useless in .NET, where you do not have to worry (in any meaningful sense) about data type sizing for arithmetic operators or any of that crap. This is the future. We have smart computers and smart IDEs and shitting up code with meaningless, misleading, wrong relics of older paradigms is counterproductive.

Quote
They kind of mean the same thing but they're used in different ways and I definitely don't want to get them confused.
But they don't mean the same thing. Speed and velocity are different. You won't get them confused if you understand your problem domain.

Quote
At any rate I don't plan on letting anyone else work on the code in the foreseeable future so I'll just leave it as is.
Bad code does not become good code because nobody else sees it. Bad habits do not magically transform into good habits when you start working with other people.

There's no reason not to do it right.

(Of course, I don't care what you per se do: but I care that newbie programmers might read this thread and think that using Hungarian is a good idea. It is not. Far better to understand your problem set to the degree where you don't have to worry about that stuff.)

Quote
With the AI, well...it's a little difficult to explain but let's just say for what I'm doing it works better this way and leave it at that.
From my own experience doing this, this claim seems odd--which is why I am asking the question. Why does it work better? What does deferring implementation of actions get you? Are you aiming for simultaneous actions for all actors? If so, why are you not strongly typing your actions, instead of relying on fuzzy strings?

Quote
As I said before this is just one of a million ways to go about making a game.  I would never dream of demanding that everyone should use this technique to make their own games.  You should do what works best for you.
Some ways of tackling problems are without question better than others. I am asking you to explain your reasoning for choosing a way that nobody else does and why it is beneficial, because I am interested in seeing if your approach provides a win over more conventional approaches--so that I may learn something here.
« Last Edit: June 29, 2010, 09:19:52 pm by Blacken »
Logged
"There's vermin fish, which fisherdwarves catch, and animal fish, which catch fisherdwarves." - Flame11235

SolarShado

  • Bay Watcher
  • Psi-Blade => Your Back
    • View Profile
Why me!? Victim of multiple ninjas :(
« Reply #11 on: June 29, 2010, 09:17:18 pm »

Blacken makes good points.
EDIT: referring mostly to reply #7

Your Creature class sounds like a good starting point, personally, I think it'd do just fine as a top-level class. No need to group items and creatures under a subclass IMO. How you divide Hostile/Friendly/etc. Creatures can be a tricky decision... really think about how your creatures will be divided from the player's point of view. Obviously you'll have Hostile/non-Hostile, will you have allies that fight beside you too? Is there a need for sentient/non-sentient or can_speak/can_not_speak, or even both?

Once that's firmly decided, you can decide how that part of your class tree will look. Can you just use Creature? You'll probably want sub-classes for intelligent/not creatures. Hostility might be better as a variable.

Items would need to be sub-divided too. Bare minimum IMO: Equipment/Use-able. These would be best as sub-classes, you could divide the classes further into weapons and armor, potions, etc. Usable items might be easiest as one class with a variable to distinguish sub-types.

Containers probably should just be a subclass on Item that can hold other Items, possibly with a check to prevent nesting Containers. Details are up to you, but it's something to keep in mind.

  • The biggest thing to keep in mind is that a class not only defines an object, but how the object can be interacted with!

For AI, I'd use a bunch of if/if-else/if-elseif statements for the deciding, with a function call to code that does the actual doing.

If you plan to use objects to represent possible actions, consider using an enumeration class (a class with a fixed number of instances). If your Action objects are immutable, this trick could be a bit more efficient.

Re: Hungarian Notation: Never used it myself. To each his own. OTOH, if you're using the same name for more than one variable, you should probably re-think your names.

NINJA'D!!!
« Last Edit: June 29, 2010, 09:27:35 pm by SolarShado »
Logged
Avid (rabid?) Linux user. Preferred flavor: Arch

Blacken

  • Bay Watcher
  • Orange Polar Bear
    • View Profile
Re: Let's Make! (Like a "Let's Play" but making a roguelike instead)
« Reply #12 on: June 29, 2010, 09:26:29 pm »

Your Creature class sounds like a good starting point, personally, I think it'd do just fine as a top-level class. No need to group items and creatures under a subclass IMO. How you divide Hostile/Friendly/etc. Creatures can be a tricky decision... really think about how your creatures will be divided from the player's point of view. Obviously you'll have Hostile/non-Hostile, will you have allies that fight beside you too? Is there a need for sentient/non-sentient or can_speak/can_not_speak, or even both?

Once that's firmly decided, you can decide how that part of your class tree will look. Can you just use Creature? You'll probably want sub-classes for intelligent/not creatures. Hostility might be better as a variable.

Well, here's the thing. Everybody does it the way I suggested, in game engines regardless of genre. Source? An ammo can and a player are both entities, because they exist in worldspace. Unreal? A mobile and a rocket launcher are both Actors. They are not different enough to treated differently at the highest levels of program logic. You can do it, but you will be duplicating code and writing in special cases that just don't need to be there. As far as a Tile is concerned (we call then Squares in Sharplike), it does not care whether something entering it is an item or a creature, just that it has to keep track of something new in its list. Why duplicate the code? What win do you get?

Quote
Items would need to be sub-divided too. Bare minimum IMO: Equipment/Use-able. These would be best as sub-classes, you could divide the classes further into weapons and armor, potions, etc. Usable items might be easiest as one class with a variable to distinguish sub-types.

Containers probably should just be a subclass on Item that can hold other Items, possibly with a check to prevent nesting Containers. Details are up to you, but it's something to keep in mind.
Ah, but now here we have a precise reason why his object model (separate top-level classes) falls down: what is the logical difference between an item container and a mobile's inventory?

I would suggest that there isn't a significant one. All the same constraints apply. And worries about "oh, creatures picking up other creatures" are not germane; this is C#, where realtime type identification is ultra-cheap. Your foreach loops can pull specific subclasses out of a container with the format "foreach (Creature in ListOfEntities)" (in the standard collections classes it will only return Entities that are also Creatures), and you can avoid issues with a simple "if (someVariable is Item)". Of course, you might want Creatures to be able to pick up other Creatures--and guess what? Now you get that for nearly free.

I think this effectively proves my point. I don't think there's a good reason to do it any other way: polymorphism is awesome precisely because of these situations.
« Last Edit: June 29, 2010, 09:32:19 pm by Blacken »
Logged
"There's vermin fish, which fisherdwarves catch, and animal fish, which catch fisherdwarves." - Flame11235

SolarShado

  • Bay Watcher
  • Psi-Blade => Your Back
    • View Profile
Re: Let's Make! (Like a "Let's Play" but making a roguelike instead)
« Reply #13 on: June 29, 2010, 09:35:02 pm »

In a 3D environment, a generic Entity class does make a lot of sense. I thought this was to be more of an ASCII/2D-grid-based game. I'm not terribly familiar with XNA or C#.

Good point about the container/actor inventory similarity... I honestly hadn't though about it like that. Even so, I'd be more likely to give every Creature a "backpack" Container than merge the functionality into a superclass. But, I've never worked on a project that needed an Entity class, so...
Logged
Avid (rabid?) Linux user. Preferred flavor: Arch

Total_Meltdown

  • Bay Watcher
  • BEEEEEEEES!!!
    • View Profile
    • Blogus Arbitrarius
Re: Let's Make! (Like a "Let's Play" but making a roguelike instead)
« Reply #14 on: June 29, 2010, 09:37:05 pm »

Lemunde, you can learn from this.

I am going to provide use cases for each sentence in SolarShado's post, which illustrate why it's exactly what you shouldn't do.


Your Creature class sounds like a good starting point, personally, I think it'd do just fine as a top-level class.
Weapons are not creatures.

No need to group items and creatures under a subclass IMO.
That's not what subclass means. If you meant "superclass" then you mean copy/pasting everything that creatures and items have in common. This is bad.

How you divide Hostile/Friendly/etc. Creatures can be a tricky decision... really think about how your creatures will be divided from the player's point of view.
What if you have more than one player?

Obviously you'll have Hostile/non-Hostile, will you have allies that fight beside you too?
What if you have more than one team/alliance?

Is there a need for sentient/non-sentient or can_speak/can_not_speak, or even both?
What is speaking? What is sentience? If characters that have behaviors are fundamentally the same as characters that don't, why not just have the base character class be able to speak, so all of your characters can speak for free, even if some don't?

Once that's firmly decided, you can decide how that part of your class tree will look. Can you just use Creature? You'll probably want sub-classes for intelligent/not creatures. Hostility might be better as a variable.
Better track on the hostility thing.

Items would need to be sub-divided too. Bare minimum IMO: Equipment/Use-able. These would be best as sub-classes, you could divide the classes further into weapons and armor, potions, etc. Usable items might be easiest as one class with a variable to distinguish sub-types.
Again, "subclasses" or "child classes" inherit from "superclasses" or "base classes", not the other way around. Other than that, your hierarchy is pretty good, right up until the "usable items" bit. Again, polymorphism is your friend. Let the language work for you.

Containers probably should just be a subclass on Item that can hold other Items, possibly with a check to prevent nesting Containers. Details are up to you, but it's something to keep in mind.
I mostly agree with this, but I'm not sure why nesting is a problem. What if you're carrying a Bag Of Shit(tm)? Also +1 to Blacken's suggestion of making a creature a container.

  • The biggest thing to keep in mind is that a class not only defines an object, but how the object can be interacted with!
The class does, and so do it's base classes. Use that to your advantage. Bags and characters can both carry items. Why write item carrying twice?

If you plan to use objects to represent possible actions, consider using an enumeration class (a class with a fixed number of instances). If your Action objects are immutable, this trick could be a bit more efficient.
This sounds like it's from Java (don't know Java, so can't say for sure). I see what you're saying, and if huge swaths of if/else if/else are your thing, at least do it correctly. I'm allergic to them personally. I get hives.


Now, I know a lot of my comments (like "what if you have more than one player?") can be answered with "but that's not how my game." I can assure you that this is not an appropriate answer. I have maintained enough code since I started doing this to know exactly what happens when shortcuts are taken in your architecture. It's not pretty.
Pages: [1] 2 3 ... 8