Jump to content

  • Log In with Google      Sign In   
  • Create Account

Nypyren

Member Since 19 Aug 2002
Offline Last Active Today, 01:38 AM

#5180375 My teams all hate eachother.

Posted by Nypyren on 14 September 2014 - 10:54 PM

Once upon a time, several coworkers and I talked about making a game in our free time (I work at a large game development studio, but we make games that we don't actually like to play ourselves). I got a basic skeleton of the game code thrown together, one of the artists whipped up some cool art, then everyone else lost motivation and I salvaged it as a simple tech demo.

What went wrong in our case?

- Everyone on the team (except for me) was only motivated by money. The main goal was to quickly throw together a vertical slice (fully functional demonstration of the core feature set) and then pitch it to management (so that we could get paid to work on it - at work), but we didn't even make it that far before everyone fizzled out, because we had...

- No leadership. We had the high-level picture of what we wanted to make, but NOBODY could agree on the details. If you can't agree on details, you can't actually implement them.


#5180289 "Permanent" pointer-like references in C#? Or design that works for t...

Posted by Nypyren on 14 September 2014 - 12:25 PM

The problem with .Net is that the class instances can actually move around in memory at runtime due to garbage collection, so you can't store a simple, long-term pointer to the address of one of their members (at least, not in the normal way you'd expect - you CAN do this with delegates).

You could make a Variable<T> class, using it to define each of the player's parameters. This would let you get a long-term reference, similar to a pointer. The downside is that it's still pretty cumbersome to use. It also incurs a performance penalty for all normal operations, not just pointer-like operations.

You could make a class which uses reflection, storing the Object and FieldInfo you want to affect, but then you lose all type safety. Performance is also not as good as it could be.

The other consideration is that you probably want to be able to create a Potion without binding it to a Player immediately. What if you're in a game with multiple players/characters and want to give the potion to a different character? You don't want to have the potion point to a player directly until you need to use it.


Here's an option that is fairly simple and clean:
 
public class Player
{
    public float HitPoints;
}

public delegate void ApplyEffectToPlayer(Player player);

public class Potion
{
    public ApplyEffectToPlayer ApplyTo;

    public Potion(ApplyEffectToPlayer applyTo)
    {
        ApplyTo = applyTo;
    }

    public void Use(Player player)
    {
        ApplyTo(player);
    }
}

public class PotionFactory
{
    public static Potion CreateHealthPotion(float healingAmount)
    {
        return new Potion(player => player.HitPoints += healingAmount);
    }
}



#5179762 The difference between Logic, Reasoning, and Thinking; Data, Information, and...

Posted by Nypyren on 11 September 2014 - 10:37 PM

Think about any program based on what its inputs and outputs are. If it's just a black box which sits there and thinks, but never produces any output, then it doesn't matter what happens inside the box. It could be curing cancer or creating a utopian society, but nobody would know. It's like data which has been sucked into a black hole - nobody outside will ever know what's in there.

If a program has output but no input, it *guarantees* the output will always the same (random number generators are seeded by timers, and the time comes from outside the program). This may be useful in some cases, but not for anything that should have changing behavior.


So for your goal, what do you want to use as input, and what do you want to get as output?


#5179756 The difference between Logic, Reasoning, and Thinking; Data, Information, and...

Posted by Nypyren on 11 September 2014 - 10:02 PM

Here is the thing with deciding what everything means myself...

Perhaps something may mean one thing to one object, and a completely different thing to something/someone else because of how that thing will be interpreted.

I don't want to have to reason about every possible occurrence that "could" happen. I would rather generalize some things, and leave things open for interpretation.

Because as situations change, so could the answer to a problem change.


Concrete requirements! Concrete!

You can achieve a "calculation that gives a different answer in different situations" with any function that has at least one input and output.

Other than that, your requirements are too vague to do anything with.

Nail down your requirements. What *exactly* do you want to do? Your goal must be something that you can break down into smaller sub-problems. The terms you use (heck, terms ANYBODY uses) don't mean anything to a computer. You need to convert your terms into things that a computer cares about. A computer only knows what bytes and instructions are. You need to take the concepts you're thinking of in your brain and refactor them until they are something that you can give to a computer.

Perhaps when I said "you GET to decide what everything means" I really should have said "you HAVE to decide what everything means".


#5179740 The difference between Logic, Reasoning, and Thinking; Data, Information, and...

Posted by Nypyren on 11 September 2014 - 08:00 PM

I'm in agreement with Alvaro.

My approach would be to pick a concrete problem of any kind (regardless of whether computers are good at it or not), and break that problem down until I can implement it. Existing definitions, especially informal ones, will not help you. When you make a program, you get to decide what everything means.


#5179227 Indie game developers getting screwed by PAX?

Posted by Nypyren on 09 September 2014 - 09:53 PM

I see a whole lot of mistakes:

- Contacting PAX without following up.
- Assuming PAX isn't completely slammed by everyone else as well.
- Complaining that life isn't fair.
- Complaining about money spent when nothing had been confirmed.

And then at the bottom:

About Elyot Grant

A former child prodigy and gold medalist in national competitions in both mathematics and computer science, Elyot has long refused to enjoy anything except video games. Elyot took more pride in winning the Reddit Starcraft Tournament than he did in earning the Computing Research Association's most prestigious research award in North America. Decried for wasting his talents, Elyot founded Lunarch Studios to pursue his true passion.


Someone seriously needs to get over themselves.


#5178433 GOTO, why are you adverse to using it

Posted by Nypyren on 05 September 2014 - 08:45 PM

Do you have any examples of the sorts of circumstances under which more modern compilers are untrustworthy?


On Android (and in extremely rare circumstances) the Mono JIT compiler can produce corrupted interface method tables which result in undefined behavior instead of just crashing.

On iOS, Mono's AOT compiler inconsistently generates either correct or incorrect code when using highly important generic interfaces such as IEnumerable<T> (especially when an array is involved).

(Both of these may be Unity-specific as Unity uses a very old version of Mono)


#5176553 CreateInstance can only be called from the main thread.

Posted by Nypyren on 27 August 2014 - 06:19 PM

So, the "main thread" is a completely different thing than "main cs". Explaining what a thread is...unfortunately a pretty complex topic and is beyond the scope of this discussion.

The correct solution in this case looks like this (like what SmkViper said):
 
public class YourClass : MonoBehaviour
{
    private BSplineMath bmath;

    void Awake() // NOTE: Unity always calls Awake on its main thread.
    {
        bmath = ScriptableObject.CreateInstance("BSplineMath") as BSplineMath;
    }
}



#5176521 c# method question

Posted by Nypyren on 27 August 2014 - 04:01 PM

A global? Seriously? Don't suggest things that will worsen his code quality.

 
I don't see you problem, this is implemented for standard class bound communication.


Just because his code is starting out as static methods doesn't mean he should get used to writing his entire program that way.

It's almost always better to use parameters and local variables instead of globals, especially in cases like this where it's embarrassingly easy to use a return value and a parameter.

EVER suggesting globals when writing code the proper way is this easy is a crime against humanity.


#5176514 c# method question

Posted by Nypyren on 27 August 2014 - 03:32 PM

A global? Seriously? Don't suggest things that will worsen his code quality.


Return the player from the character creation function and then pass it to the runGame function:
 
namespace TextBasedRPGv0._2
{
    class Game
    {
            public class Character
            {
                public float maxHealth;
                public float currentHealth;
                public float maxMana;
                public float currentMana;
                public float Damage;
                public float Defence;

                public int level;
                public int strength;
                public int stamina;
                public int agility;
                public int speed;
                public int intelligence;
                public int wisdom;

            }

            public class Player: Character
            {
                public string userName;
                public string userProf;
            
                public string Warrior;
                public string Rogue;
                public string Mage;

                public float exp;
                public float expUntilNextLevel;
                public float expNextLevel;

            }

            public static Player characterCreation()
            {
                while (true)
                {
                    Player player;
                    player = new Player();

                    Console.WriteLine("Name your character.");
                    player.userName = Console.ReadLine();
                    Console.WriteLine("");
                    int chooseProf = 1;
                    Console.WriteLine("Choose your character's profession. (Warrior, Rogue or Mage)");

                    while (chooseProf != 0)
                    {
                        player.userProf = Console.ReadLine();

                        switch (player.userProf)
                        {
                            case "Warrior":

                                player.level = 1;
                                player.exp = 0;
                                player.strength = 7;
                                player.stamina = 6;
                                player.agility = 4;
                                player.speed = 4;
                                player.intelligence = 3;
                                player.wisdom = 3;

                                player.maxHealth = ((player.strength + player.stamina) * (player.level * 2)) + ((player.agility + player.speed + player.intelligence + player.wisdom) / (player.level * 2));
                                player.currentHealth = player.maxHealth;
                                player.maxMana = ((player.stamina + player.wisdom) * (player.level * 2)) + ((player.agility + player.speed + player.strength + player.intelligence) / (player.level * 2));
                                player.currentMana = player.maxMana;
                                player.Damage = ((player.strength * player.agility) - (player.agility / (player.level * 2) + player.speed)) / 2;
                                player.Defence = 0.05f;

                                Console.WriteLine("You are a level " + player.level + " Warrior with:");
                                chooseProf = 0;
                                break;
                            case "Rogue":

                                player.level = 1;
                                player.exp = 0;
                                player.strength = 3;
                                player.stamina = 5;
                                player.agility = 7;
                                player.speed = 6;
                                player.intelligence = 4;
                                player.wisdom = 2;

                                player.maxHealth = ((player.strength + player.speed) * (player.level * 2)) + ((player.agility + player.stamina + player.intelligence + player.wisdom) / (player.level * 2));
                                player.currentHealth = player.maxHealth;
                                player.maxMana = ((player.speed + player.wisdom) * (player.level * 2)) + ((player.agility + player.intelligence + player.strength + player.stamina) / (player.level * 2));
                                player.currentMana = player.maxMana;
                                player.Damage = ((player.strength * player.agility) + (player.agility / (player.level * 2) + player.speed)) / 2;
                                player.Defence = 0.04f;

                                Console.WriteLine("You are a level " + player.level + " Rogue with:");
                                chooseProf = 0;
                                break;
                            case "Mage":

                                player.level = 1;
                                player.exp = 0;
                                player.strength = 2;
                                player.stamina = 3;
                                player.agility = 4;
                                player.speed = 5;
                                player.intelligence = 6;
                                player.wisdom = 7;

                                player.maxHealth = ((player.strength + player.wisdom) * (player.level * 2)) + ((player.agility + player.speed + player.intelligence + player.stamina) / (player.level * 2));
                                player.currentHealth = player.maxHealth;
                                player.maxMana = ((player.intelligence + player.wisdom) * (player.level * 2)) + ((player.agility + player.speed + player.strength + player.stamina) / (player.level * 2));
                                player.currentMana = player.maxMana;
                                player.Damage = ((player.intelligence * player.agility) - (player.agility / (player.level * 2)) + player.wisdom) / 2;
                                player.Defence = 0.03f;

                                Console.WriteLine("You are a level " + player.level + " Mage with:");
                                chooseProf = 0;
                                break;
                        }
                    }

                    Console.WriteLine(player.strength + " strength");
                    Console.WriteLine(player.stamina + " stamina");
                    Console.WriteLine(player.agility + " agility");
                    Console.WriteLine(player.speed + " speed");
                    Console.WriteLine(player.intelligence + " intelligence");
                    Console.WriteLine(player.wisdom + " wisdom");
                    Console.WriteLine("Your max health is " + player.maxHealth + ".");
                    Console.WriteLine("Your max mana is " + player.maxMana + ".");
                    Console.WriteLine("Your damage is " + player.Damage + ".");
                    Console.WriteLine("(press enter to continue)");
                    Console.ReadLine();
                    Console.Clear();

                    return player;
                }
            }
            
            public static void runGame(Player player)
            {            
                Console.WriteLine(player.userName);
                  
            }

        public static void Main(string[] args)
        {          
            Player player = characterCreation();
            
            runGame(player);
           
            Console.ReadLine();
        }

        
    }
}



#5176497 List of generic objects

Posted by Nypyren on 27 August 2014 - 01:38 PM

Hmm, having the Unit itself create more creatures seems odd, but without knowing anything about how your codebase is structured, here's one thing you can do (factory delegate).
 
public class Unit
{
    public readonly Type m_type;
    
    List<Creature> critters = new List<Creature>();
    
    Func<Creature> m_creationDelegate;

    public Unit(Type type, Func<Creature> creationDelegate)
    {
        m_type = type;
        m_creationDelegate = creationDelegate;
    }

    public void Spawn(int count)
    {
        for (int i=0; i<count; ++i)
            critters.Add(m_creationDelegate()); // invokes the delegate which returns a Creature.
    }
}

// ..... elsewhere

void ExampleUsageFunction()
{
    Unit goblinUnit = new Unit(typeof(Goblin), () => new Goblin()); // This lambda expression just creates a default Goblin.
}
This allows maximum flexibility - you can use anything which returns a Creature. If you need to, you can modify the function signature to allow the Unit to pass creation parameters to the creation delegate:

 
public class Unit
{
    public readonly Type m_type;
    
    public List<Creature> critters = new List<Creature>();
    
    Func<Unit,Creature> m_creationDelegate;

    public Unit(Type type, Func<Unit,Creature> creationDelegate)
    {
        m_type = type;
        m_creationDelegate = creationDelegate;
    }

    public void Spawn(int count)
    {
        for (int i=0; i<count; ++i)
            critters.Add(m_creationDelegate(this)); // invokes the delegate which returns a Creature.
    }
}

// ..... elsewhere

Unit MakeGoblinUnitWithLeader()
{
    return new Unit(typeof(Goblin), unit =>
    {
        var goblin = new Goblin();
        if (unit.critters.Count == 0) // this is the first Goblin being spawned in the Unit
            goblin.IsLeader = true; // The first Goblin being spawned in a Unit is the Leader (I'm just inventing a contrived example here...)
        return goblin;
    });
}



#5176354 List of generic objects

Posted by Nypyren on 26 August 2014 - 10:54 PM

If this is what you want...

- Unit to only contain one specific type of Creature.
- Armies to contain Units, where different Units can have different Creatures.

...then this is what I would do:

- Make a base "Unit" class which is not generic.
- Make a "Unit<T>" class which derives from Unit.
- Have Army contain a List<Unit> instead of List<Unit<T>>.

NOTE: You can still break a Unit's single-type nature by adding creatures of a more derived type than T. It only prevents you from adding Creatures of a more basic type. If your Creature hierarchy is entirely abstract and sealed classes, then this will work fine.


Instead of using generics, you can enforce a specific, single Creature type in a different manner:

- Remove the generic T from the Unit completely (same as first suggestion).
- Give the Unit a "public readonly Type Type;" member which is set by the constructor.
- Change the Unit's List to List<Creature> (same as the first suggestion).
- Make your Unit's Add method only allow the exact type you specified in the ctor: (item.GetType() == Type)
- Make sure you cannot bypass the Add method (you can make Unit implement IList and restrict access to the internal collection - personally I would write my own collection separate from Unit if this kind of type safety was a major concern).


Lastly, if you don't actually care about having a single-Creature-type Unit restriction, then just remove the generics from your own classes and methods entirely:

- Unit.critters : List<Creature>
- Army.units : List<Unit>


#5174355 How can I integrate a script project into my game server?

Posted by Nypyren on 17 August 2014 - 09:41 PM

The circular reference is only bad at build time. You can just make it so the game server project doesn't directly reference the script project, but can still load it using reflection. There's no problem once it's loaded.

Here's what I've done in the past:

- In your game server project, define an interface or base class which something in your script project derives from. The interface should at least contain a "Initialize" method of some kind. The function can be static or an instance, whichever you want. You can add other methods as necessary. Think of this as the "Main" function for your script. You can use attributes as well, if you want.

- Set your script project to reference your game server project.

- Make sure your project configuration settings are set so that the script project is always built and copied to the game server project's output folder.

- When your game server runs, it can find all script projects by looking in its working folder for .DLLs. It can then load those using Assembly.LoadFile. LoadFile returns an Assembly object; you can search this assembly for type(s) which inherit from your interface/base class, instantiate them (if necessary) and then call the Initialize method using reflection.

- When your script's Initialize function is called, it can start calling methods in the game server project like normal, which will let you do anything you need to from that point on.


#5174144 I have this collision detection concept I want to discuss

Posted by Nypyren on 16 August 2014 - 02:48 PM

Anyways I don't think anyone would help now, the general rule for programming places like this is if it  isn't clear and to the point by the first post it's ignored so I guess I'll just go solo now until I really made sure the concept is perfect.


The problem is that your posts use terms and diagrams that ONLY YOU are familiar with. We can't tell what you mean by "floorpad", "landpad" or what your diagrams are supposed to represent. These are terms that you came up with, so don't expect any of us to automatically know what you mean by them.

If you don't use words that people understand, or define them in terms of what people understand, we won't know what you're talking about.

- What is a floorpad?
- What is a landpad?
- What do you mean by "wall object"?
- Is your map grid-based?
- Are your wall objects aligned to anything?
- Is your character movement aligned to tiles?


#5173703 Avoiding unnessecary if/else choice in loop for Virtual Camera

Posted by Nypyren on 14 August 2014 - 03:36 PM

Store the projection matrix as a member variable and move the projection matrix setup into a function that's only run when initializing the class or when changing the isPerspectiveOn variable.




PARTNERS