Bay 12 Games Forum

Please login or register.

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

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

Blacken

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

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.

This can't be repeated often enough. Even if you have no intentions of having more than one player, the design considerations that you will be forced to take into account by making it possible will result in a better end design.

You never want to settle for "good enough." Because, two days or two weeks or two months or two years from now, it might not be "good enough."
« Last Edit: June 29, 2010, 09:41:10 pm 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 #16 on: June 29, 2010, 09:57:48 pm »

Whew!  Lot's to respond to.  I'll just summarize by saying that much of what has been discussed I have already considered.  There's a few tidbits here and there that should be helpful.  It's rare that I have the opportunity to allow others to see how I go about making a game which is part of the reason I started this thread.  Well, back to the grind.  That sword's not gonna make itself!
Logged

Blacken

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

Oh. Nice. You've "considered" it. How about you help actually foster the dialogue here by explaining why you have chosen not to go this route? How about you explain the design decisions behind this, and why your way better achieves your goals, so we can actually have a meaningful conversation and maybe some people can actually learn something?
Logged
"There's vermin fish, which fisherdwarves catch, and animal fish, which catch fisherdwarves." - Flame11235

Karantza

  • Escaped Lunatic
  • It's a Trap?
    • View Profile
Re: Let's Make! (Like a "Let's Play" but making a roguelike instead)
« Reply #18 on: June 29, 2010, 10:10:05 pm »

Hey. Read through the topic, and I have to say, that sounds like a neat project, and definitely a good learning experience. Don't let anyone tell you otherwise, C# is a perfectly fine language to use. I know C and C++ *very* well, and if I were writing a roguelike, I'd be using C#.

As for putting in my 2 cents on advice, I'm gonna have to mirror Meltdown and Blacken; using inheritance is *Awesome*, and you will be a much better programmer once you see how often you can use it.

I mean, think about it this way. This is an example from a 3d game engine I wrote (in C++, but I'll use C# terms) a few years ago with Meltdown. We had a world full of a bunch of stuff, and a scripting language that wanted to be able to mess with it all. We had *one* base class, Object, that implemented just enough to hook it into the scripts. From that, we had all sorts of things - vectors, timers, etc. Things we wanted to script, but weren't in the world.

One of the child classes of Object was WorldObject. This added a position and velocity, and the networking code to syncronize it, etc. Nothing else. This is still an abstract class; it can't actually be used yet. Off of WorldObject we wrote Mesh, Billboard, ParticleSystem, RigidBody, etc. Most of the game objects. Eventually, down the line, we'd have things like characters and weapons and pickups.

But in none of those base classes did we ever have to worry about storing the position of the object, or how it was handled on the network. By using inheritance, we were able to write all that logic exactly once.

I'd go so far as to say that if you're ever copy-and-pasting anything, you could use Inheritance and make your life easier. Suppose you have your Monster and Projectile classes. (Off of those you might have, say, Goblin and MagicMissile.) Each of those might have a Think() function, in which it does things like AI or movement or whatever. Each sub-class would reimplement that to do it's specific behavior. In your main loop, you'd have to say something like:
Code: [Select]
foreach (Monster m in myMonsters) { m.Think() }
foreach (Projectile p in myProjectiles) { p.Think() } 
 
This is a perfect place for an Interface, IThinkable:
Code: [Select]
public interface IThinkable {
    public void Think();
}

public class Monster : IThinkable
{ ... }


public class Projectile : IThinkable
{ ... }

And then in your main loop part:
Code: [Select]
foreach(IThinkable thinker in myThinkables) { thinker.Think() }
And the benefit is, if you ever want to add something else that thinks - say, next month you decide that items on the floor really should be able to Think, if they want to, say, degrade from exposure to the elements - then you can just inherit from IThinkable, and all your old code will automatically work with the new classes. It gets rid of the massive potential for bugs or missing one little copy.

You can never implement too many interfaces. Whenever you find yourself doing anything the same way in multiple classes, you'll probably want to make an interface for it.
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 #19 on: June 29, 2010, 10:15:05 pm »

A bunch of smart-person baloney.

But he probably already considered that.

Acanthus117

  • Bay Watcher
  • Angry Writer
    • View Profile
Re: Let's Make! (Like a "Let's Play" but making a roguelike instead)
« Reply #20 on: June 29, 2010, 10:29:04 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
Is apparently a Lizardman. ಠ_ಠ
YOU DOUBLE PENIS
"The pessimist is either always right or pleasantly surprised; he cherishes that which is good because he knows it cannot last."

Lemunde

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

Okay, before this gets out of hand I want to make clear that I do understand everything about inheritance.  I hadn't used it yet because the amount of redundancy seemed minimal and I wanted to focus on getting a few things out of the way first.  However I have since gone back and added a general GameObject class that stores information such as position, graphical data, null status and name with more to be added as needed.  So now the Creature class and the new Item class inherits from GameObject and my program smells like flowers.   ;)
Logged

Virex

  • Bay Watcher
  • Subjects interest attracted. Annalyses pending...
    • View Profile
Re: Let's Make! (Like a "Let's Play" but making a roguelike instead)
« Reply #22 on: June 30, 2010, 04:39:47 am »

Remember that if you ever find yourself needing some extra differentiation in the inheritance structure of the program, C# objects can inherit from only one class, but from any number of interfaces. So if Fooclass inherits from Barclass, but you also need it to inherit some things from Appleclass, you can use an interface IApple to make Fooclass inherit the things it needs from Appleclass. I'm not a C# programmer though so you'll need to figure out how to implement that properly on your own ;)
Logged

Lemunde

  • Bay Watcher
    • View Profile
Re: Let's Make! (Like a "Let's Play" but making a roguelike instead)
« Reply #23 on: June 30, 2010, 11:44:07 am »

Who would have thought it would feel so good to get slashed to pieces by a goblin!  I still need to make a few adjustments before I move on to something else but I got all the hard stuff out of the way.  And for your viewing pleasure here's a screenshot!

Spoiler (click to show/hide)
Logged

Virex

  • Bay Watcher
  • Subjects interest attracted. Annalyses pending...
    • View Profile
Re: Let's Make! (Like a "Let's Play" but making a roguelike instead)
« Reply #24 on: June 30, 2010, 04:41:50 pm »

 :o  that goblin looks waaaaay to cute...
Logged

Urist McOverlord

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

Random observation 1:
:o  that goblin looks waaaaay to cute...

Random observation 2:
Hey! I actually understood more of this than I thought I would! I still am dealing with technological powers far beyond my ken, but not quite as far beyond my ken.

EDIT for spelling. Get it together, self.
« Last Edit: July 01, 2010, 06:49:57 pm by Urist McOverlord »
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.

Normandy

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

If you're doing animations between every frame, I do have a suggestion:

Instead of having discrete steps between every frame, internally use a time accumulator and a simplified physics engine. Except instead of accumulating time passed, accumulate time that your character spends. Say if swinging your sword takes 1500 ms, add 1.5 to some value timeDelay. Then, in your update() function (called every frame), do something like this (note that this is pseudo-code, I haven't used XNA in a while):

Code: [Select]
timeAccumulator += lastFrameLength();
while (timeAccumulator > 0.0f) {
    if (timeDelay <= 0.0f) {
        timeAccumulator = 0.0f;
    } else {
        // Remember that it is important to use a constant timestep unless you know what you're doing
        updatePhysics(0.01f);
        timeDelay -= 0.01f;
        timeAccumulator -= 0.01f;
    }
}

Then, you will take care of two birds with one stone; the problem of relative delays (i.e. adding 'speed' traits to creatures), smoothly animating things like projectiles or flying bodies with respect to one another.

I actually implemented this once with libtcod; it is rather unintuitive at first to change from step-based gameplay to what is effectively real-time gameplay, but IMO the results were worth it. I very simply added and animated moving projectiles by giving entities velocities. And since there were still discrete tiles, I did not have to bother with collision detection.

Also, you can implement slow-motion by changing timeAccumulator -= 0.01f; to timeAccumulator -= 0.01f / timeRate;, so if timeRate = 2.0f, twice as many updates get called per frame, and time 'happens' twice as fast, or if timeRate = 0.5f, time is slowed to half speed.

EDIT: I should be clearer, it only affects speed of animation.
« Last Edit: June 30, 2010, 08:26:55 pm by Normandy »
Logged

ILikePie

  • Bay Watcher
  • Call me Ron
    • View Profile
Re: Let's Make! (Like a "Let's Play" but making a roguelike instead)
« Reply #27 on: July 01, 2010, 03:22:23 am »

Who would have thought it would feel so good to get slashed to pieces by a goblin!  I still need to make a few adjustments before I move on to something else but I got all the hard stuff out of the way.  And for your viewing pleasure here's a screenshot!

Spoiler (click to show/hide)
Oh, was thinking of something entirely text based, that looks great.
Logged

Lemunde

  • Bay Watcher
    • View Profile
Re: Let's Make! (Like a "Let's Play" but making a roguelike instead)
« Reply #28 on: July 01, 2010, 08:29:34 am »

If you're doing animations between every frame, I do have a suggestion:

Instead of having discrete steps between every frame, internally use a time accumulator and a simplified physics engine. Except instead of accumulating time passed, accumulate time that your character spends. Say if swinging your sword takes 1500 ms, add 1.5 to some value timeDelay. Then, in your update() function (called every frame), do something like this (note that this is pseudo-code, I haven't used XNA in a while):

Code: [Select]
timeAccumulator += lastFrameLength();
while (timeAccumulator > 0.0f) {
    if (timeDelay <= 0.0f) {
        timeAccumulator = 0.0f;
    } else {
        // Remember that it is important to use a constant timestep unless you know what you're doing
        updatePhysics(0.01f);
        timeDelay -= 0.01f;
        timeAccumulator -= 0.01f;
    }
}

Then, you will take care of two birds with one stone; the problem of relative delays (i.e. adding 'speed' traits to creatures), smoothly animating things like projectiles or flying bodies with respect to one another.

I actually implemented this once with libtcod; it is rather unintuitive at first to change from step-based gameplay to what is effectively real-time gameplay, but IMO the results were worth it. I very simply added and animated moving projectiles by giving entities velocities. And since there were still discrete tiles, I did not have to bother with collision detection.

Also, you can implement slow-motion by changing timeAccumulator -= 0.01f; to timeAccumulator -= 0.01f / timeRate;, so if timeRate = 2.0f, twice as many updates get called per frame, and time 'happens' twice as fast, or if timeRate = 0.5f, time is slowed to half speed.

EDIT: I should be clearer, it only affects speed of animation.

I think I see what you're doing there and I think I'm doing something similar.  Currently I'm using a variable called RoundTimer that accumulates every frame.  Once RoundTimer reaches 1 it resets to 0 and the next round begins.  The animations base everything off of RoundTimer.  When I go to draw a creature I don't draw it at it's actual location but using the formula DrawLocation = OldTilePosition + ((NewTilePosition - OldTilePosition) * RoundTimer).  This has the benefit of making their location pretty exact between rounds.

Unfortunately it means that every Creature is forced to move and act at the same speed.  If I want to get different speeds I will need to give each Creature it's own RoundTimer and run all the calculations on it's true tile position rather than it's old or new tile position.  This is probably what I'm going to work on next as it's something I'll want to get working before I make too many functions that rely on the Creature's tile location.

Edit: Well that was a lot easier than I thought it would be.  I need to do some more testing to make sure everything is working right but I got Creatures moving at different speeds now. 

My normal speed human just had an interesting battle with a somewhat slower goblin.  My human would move away and the goblin would follow, appropriately stopping mid-round when my human finished his.  Of course since tile positions are now based off of true positions he can now get two hits in on me before I move out of range.  If I made him a little slower I'm sure he could just get one hit in.  When my human strikes back it's a different story.  My human is roughly 1.5 times faster than the goblin so he gets a few more hits in.  The sluggish goblin can't take too much of it so it's not long before he dies.
« Last Edit: July 01, 2010, 10:19:13 am by Lemunde »
Logged

DrPizza

  • Bay Watcher
    • View Profile
    • Ars Technica
Re: Let's Make! (Like a "Let's Play" but making a roguelike instead)
« Reply #29 on: July 01, 2010, 02:54:28 pm »

Oh. Nice. You've "considered" it. How about you help actually foster the dialogue here by explaining why you have chosen not to go this route? How about you explain the design decisions behind this, and why your way better achieves your goals, so we can actually have a meaningful conversation and maybe some people can actually learn something?
Stool brory, co.
Logged
Pages: 1 [2] 3 4 ... 8