Bay 12 Games Forum

Please login or register.

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

Author Topic: Aqizzar makes a game  (Read 15475 times)

Johuotar

  • Bay Watcher
    • View Profile
    • Some game projects
Re: Aqizzar Finally Starts Making A Game
« Reply #30 on: February 08, 2013, 03:57:50 am »

Following.
Logged
[img height=x width=y]http://LINK TO IMAGE HERE[/img]
The Toad hops in mysterious ways.
This pure mountain spring water is indispensable. Literally. I'm out of paper cups.

Aqizzar

  • Bay Watcher
  • There is no 'U'.
    • View Profile
Re: Aqizzar Finally Starts Making A Game
« Reply #31 on: February 08, 2013, 09:44:53 pm »

Had an interesting conversation at work today.  Wound up talking to my boss for half an hour about feeling restless because I'm not doing anything new at work, and he couldn't agree more.  Pitched the idea of doing a "side project" with me, to make a WPF application that would make a certain aspect of our job less of a pain in the ass.  Sounds cool, except: "You'll be working on your own time and the CEO doesn't for unscheduled work, you understand of course, but blah blah blah" I stopped listening at that point.

Sorry jefe, but I've got plenty of stuff I'd rather be coding for free.  Praise is cool and all but I have nooo shortage of stuff to stay entertained on my own time.



Libtcod sample terminal sheet, y u no Codepage437?  Dammit, I spent like half an twenty minutes giving myself carpal-tunnel making that character-interpreter method, because C#'s included char-to-byte conversion blows moosecock.  Now I either have to rewrite the list or edit the graphic.  Pfft.

Well, at least all of my fundamental drawing elements work.  I could use some more global drawing classes, but the skeleton is officially alive.  Yeah, you heard me.
Logged
And here is where my beef pops up like a looming awkward boner.
Please amplify your relaxed states.
Quote from: PTTG??
The ancients built these quote pyramids to forever store vast quantities of rage.

GalenEvil

  • Bay Watcher
    • View Profile
    • Mac-Man Games
Re: Aqizzar Finally Starts Making A Game
« Reply #32 on: February 08, 2013, 10:59:12 pm »

I thought that char -> byte would be "(byte)('the char');" or at maybe "(byte)((int)('the char'));"? I think that might limit you to just ASCII though, so extra stuff in the (byte)((int)('the char')) part would be necessary if you were using characters outside of ASCII. Why do you need to convert from char to byte?
Logged
Fun is Fun......Done is Done... or is that Done is !!FUN!!?
Quote from: Mr Frog
Digging's a lot like surgery, see -- you grab the sharp thing and then drive the sharp end of the sharp thing in as hard as you can and then stuff goes flying and then stuff falls out and then there's a big hole and you're done. I kinda wish there was more screaming, but rocks don't hurt so I guess it can't be helped.

Aqizzar

  • Bay Watcher
  • There is no 'U'.
    • View Profile
Re: Aqizzar Finally Starts Making A Game
« Reply #33 on: February 08, 2013, 11:12:27 pm »

I thought that char -> byte would be "(byte)('the char');" or at maybe "(byte)((int)('the char'));"? I think that might limit you to just ASCII though, so extra stuff in the (byte)((int)('the char')) part would be necessary if you were using characters outside of ASCII. Why do you need to convert from char to byte?

I need to convert char to bytes because Libtcod takes in a byte as it's "what to print" value, because it doesn't actually print characters just tile locations from the sheet it's told to print from.  I tried using the C# standard Encoding.ASCII.GetBytes() method, as well as Encoding.UTF8 and Encoding.Unicode.  None of them returned values of any use for Libtcod's purposes.

Besides, at least now I can custom-map any key to any tile I want, it's just kinda tedious.
Logged
And here is where my beef pops up like a looming awkward boner.
Please amplify your relaxed states.
Quote from: PTTG??
The ancients built these quote pyramids to forever store vast quantities of rage.

GalenEvil

  • Bay Watcher
    • View Profile
    • Mac-Man Games
Re: Aqizzar Finally Starts Making A Game
« Reply #34 on: February 08, 2013, 11:27:47 pm »

Ah, that makes sense. I haven't played with libtcod before heh. It's good that you can now do custom key-maps at least :D
Logged
Fun is Fun......Done is Done... or is that Done is !!FUN!!?
Quote from: Mr Frog
Digging's a lot like surgery, see -- you grab the sharp thing and then drive the sharp end of the sharp thing in as hard as you can and then stuff goes flying and then stuff falls out and then there's a big hole and you're done. I kinda wish there was more screaming, but rocks don't hurt so I guess it can't be helped.

Max White

  • Bay Watcher
  • Still not hollowed!
    • View Profile
Re: Aqizzar Finally Starts Making A Game
« Reply #35 on: February 10, 2013, 10:52:44 pm »

That and pray for Max White to show up and take pity on me again, because nothing ever really changes.
I HAVE A LIFE YOU KNOW!
No, not really. Ok let's get this show on the road. I'll show you how I like to set up Libtcod with state pattern to make life easy for all involved.
Basically libtcod is a hunk of well running shit designed by a maths guy who liked numbers, rather than a programmer who designs things to be in any possible way usable. But, with just a little effort, we can make things a little easier for ourselves.

Firstly, it sounds like you already have the basics going, but just to make sure, and also for anybody at home who wants to bake their own:
After downloading the .net wrapper for Libtcod (And also a copy of the terminal.png, not included with the standard download for excuses) add a reference to libtcod-net.
Now to your project (Not as a reference) add libtcod-VS.dll, libtcod-net-unmanaged.dll, SDL.dll, zlib1.dll and terminal.png (Or what ever file format you have, I'm 80% sure others work)
Remember to select all the files you just added to your project and go down to your properties window. Change to 'Copy if newer'
For good measure, run that once, just so that it copies all the files and you will never have to think about it again.

Now onto the fun bit, the code! First, make a new class called 'Game' and give it a public void method with an empty signature called 'Run'. Should look like this.

Code: [Select]
    class Game
    {
        public void Run()
        {
        }
    }

Now back in your main, create a new game instance and call its run method. That is all for the main. Hopefully, for some time at least, you will never need to modify that. Anyway, before we can continue, we need a new abstract class.
Call this new class GameState and give it the methods 'internal abstract void Draw(TCODConsole console)' and 'internal abstract void Update(TCODKey input);'
Yes, I know we could be using partial classes right now to make the GameState part of the game DO NOT CARE RIGHT NOW. It is an indie game. The fact that we are using state pattern instead of a giant IF block already stinks of high class.
Anyway, code should look like this
Code: [Select]
    abstract class GameState
    {
        internal abstract void Update(TCODKey input);
        internal abstract void Draw(TCODConsole console);
    }

Now you are going to need to allow your GameState to see your Game, so add a protected attribute called game and also make a protected constructor taking a Game as a parameter.

Code: [Select]
    abstract class GameState
    {
        protected Game game;

        protected GameState(Game game)
        {
            this.game = game;
        }

        internal abstract void Update(TCODKey input);
        internal abstract void Draw(TCODConsole console);
    }

Ok, that is all we need for our GameState! Back to the game folks.
First, throw in a bool called 'quitting', an instance of a GameState called 'state' and two methods, one called 'Quit()' and another called 'SetState(GameState state)'. Have Quit() flag 'quitting' as true and SetState() reassign 'state'

Code: [Select]
    class Game
    {
        private bool quitting;
        private GameState state;

        public void Run()
        {
        }

        internal void Quit()
        {
            this.quitting = true;
        }

        internal void SetState(GameState state)
        {
            this.state = state;
        }
    }

Ok, now all we need to do is define a game state to actually run, and build the game loop. Let's start with the loop.
There are better ways to do this than hard coding, but let's start simple and call TCODConsole.initRoot(sizeX, sizeY, "NameOfGameHere");
Next, set quitting to false.
Now comment out what you are about to do, because you will need a class we haven't made yet, but call 'this.state = new MainMenuState(this);'
Ok, so as a little qwerk of what we are doing and how libtcod works, we want to clear, draw to and flush our console before we do anything else. Remember, you are drawing your game by calling state.Draw(TCODConsole.root)
Now start a loop with the condition !quitting. This is your main game loop.
Inside it, first call 'state.Update(TCODConsole.waitForKeypress(false))'
Then, just like you did before we entered the loop, clear, draw and flush. All in all, should look like this

Code: [Select]
        public void Run()
        {
            TCODConsole.initRoot(120, 70, "Dicks");

            this.quitting = false;
            //this.state = new MainMenuState(this);

            TCODConsole.root.clear();
            this.state.Draw(TCODConsole.root);
            TCODConsole.flush();

            while (!quitting)
            {
                this.state.Update(TCODConsole.waitForKeypress(false);

                TCODConsole.root.clear();
                this.state.Draw(TCODConsole.root);
                TCODConsole.flush();
            }
        }


We are almost done!
Part II (Coming soon) will introduce you to HOLY FUCK WE CAN DO THAT as well as actually starting to do the bit where it is your game.

Skyrunner

  • Bay Watcher
  • ?!?!
    • View Profile
    • Portfolio
Re: Aqizzar Finally Starts Making A Game
« Reply #36 on: February 10, 2013, 11:13:44 pm »

...OHHHH. This is what the GameState class in the engine I have is for. o_O I was wondering what it was.
Logged

bay12 lower boards IRC:irc.darkmyst.org @ #bay12lb
"Oh, they never lie. They dissemble, evade, prevaricate, confoud, confuse, distract, obscure, subtly misrepresent and willfully misunderstand with what often appears to be a positively gleeful relish ... but they never lie" -- Look To Windward

Max White

  • Bay Watcher
  • Still not hollowed!
    • View Profile
Re: Aqizzar Finally Starts Making A Game
« Reply #37 on: February 10, 2013, 11:23:44 pm »

Now, I'm about 90% sure I have already shown this off in the programming thread, so Aqizzar you might already know this, but I'm writing this tutorial for anybody interested and there is always the chance one of us forgot something, so time for the 'My language is better than yours' part of the show.
Sometimes, when using somebody elses classes, they will be missing some functionality that would just make life so much easier for you. ALWAYS when using libtcod there will be functionality missing that will make life bearable for you. As such, before we continue I will show everybody how we can very easily get around this problem in c#. This is a great language feature that Java really could use, like so many other little syntax things out there...
We can add our own methods onto other peoples classes using the 'this' keyword with the first parameter of a static method. This is a little hard to explain, so how about I just show you all.

Code: [Select]
    static class ConsoleExtender
    {       
public static void ColorPrint(this TCODConsole console, int x, int y, string s, TCODColor color)
        {
            console.print(x, y, s);
            for (int i = 0; i < s.Length; i++)
            {
                console.setCharForeground(x + i, y, color);
            }
        }
    }

See how the first parameter has the 'this' keyword before the type? That allows us to call it as a method of that class. For example, I could call 'TCODConsole.root.ColorPrint(4, 4, "Hello World", TCODColor.darkGreen);' Even though 'ColorPrint' belongs to the ConsoleExtender class. It is a great little language feature that allows us to add out own service level functionality where we find a need.
Here is a few more methods I like to use
Code: [Select]
        public static void DrawBackgroundRectangle(this TCODConsole console, int x, int y, int width, int height, TCODColor backColor, float coef = 1f)
        {
            for (int a = 0; a < width; a++)
            {
                for (int b = 0; b < height; b++)
                {
                    console.setCharBackground(x + a, y + b, TCODColor.Interpolate(console.getCharBackground(x + a, y + b), backColor, coef));
                }
            }
        }
        public static void DrawForegroundRectangle(this TCODConsole console, int x, int y, int width, int height, TCODColor foreColor, float coef = 1f)
        {
            for (int a = 0; a < width; a++)
            {
                for (int b = 0; b < height; b++)
                {
                    console.setCharForeground(x + a, y + b, TCODColor.Interpolate(console.getCharForeground(x + a, y + b), foreColor, coef));
                }
            }
        }
Trust me, you will want to use them rather than the 'SetBackground' and 'SetForeground' methods that come with libtcod. They don't work the way you want them to. Basically they need to be flushed twice, rather than at the same time as everything else, causing this odd flicker as everything else updates but the back ground doesn't.

Now, lets get around to that MainMenuState as an example of how to use what we just set up. First game your class called 'MainMenuState' and have it extend GameState, as well as override its abstract methods. Add a constructor that takes a Game as an argument and passes it to its base.

Code: [Select]
    class MainMenuState : GameState
    {
        internal MainMenuState(Game game)
            : base (game)
        {
        }

        internal override void Update(TCODKey input)
        {
        }

        internal override void Draw(TCODConsole console)
        {
        }
    }

Don't forget to uncomment that line of code in your Game class!
Now you can pretty much go wild in making it all look how you like. For example:
Code: [Select]
    class MainMenuState : GameState
    {
        bool newGame;
        internal MainMenuState(Game game)
            : base (game)
        {
            newGame = true;
        }

        internal override void Update(TCODKey input)
        {
            switch (input.KeyCode)
            {
                case (TCODKeyCode.Enter) :
                    if (newGame) game.SetState(new PlayingState(game)); //This is how you change between states
                    else game.Quit(); //This is how you quit the game
                    break;
                case (TCODKeyCode.Up): newGame = true;
                    break;
                    case (TCODKeyCode.Down) newGame = false;
                    break;
            }
        }

        internal override void Draw(TCODConsole console)
        {
            console.DrawBackgroundRectangle(0, 0, console.getWidth(), console.getHeight(), TCODColor.azure);
            console.ColorPrint(4, 4, "New Game", TCODColor.lightestBlue);
            console.ColorPrint(4, 5, "Quit", TCODColor.lightestBlue);
            if (newGame) console.ColorPrint(2, 4, ">", TCODColor.lightestBlue);
            else console.ColorPrint(2, 5, ">", TCODColor.lightestBlue);
        }
    }

As you can see, pretty easy to build a simple main menu.
This method forces a separation between the update logic and the draw logic. THIS IS DAMN IMPORTANT! Nothing outside of the Game class should ever, ever call TCODConsole.root. It has access to that object as a parameter. It also allows you to easy swap between states and close the game.

If there are any errors, please tell me. I am on a library computer without a compiler and so can't test any of this. I am literally writing this up in notepad, going off memory and the scrappy docs that libtcod has. There are bound to be inconsistencies, so just tell me what you find and I'll try to fix it all up.

Aqizzar

  • Bay Watcher
  • There is no 'U'.
    • View Profile
Re: Aqizzar Finally Starts Making A Game
« Reply #38 on: February 11, 2013, 12:50:37 am »

Well thanks for stopping by Max, always good to see you in action.  You'll be pleased to know that I already kinda sorta implemented most of that stuff, in a more hamfisted way.  I don't have any class extensions (you can do that? wow) but I do have a static "display" class that all screen input goes through, so the updating and drawing logic is separated.

I think your "GameState" system is a bit fancier than my setup, but it's the same fundamental idea.  The whole game is based around "screens" that have all of their own interface and activity logic built into them, with a very simple loop in the main Program body to keep the game loop going.  Each time a screen is called, it's created with a reference to the screen that called it, so when you close out of a screen it takes you back to the previous one with all settings preserved.  There's also room for some global screen-elements, so things like message scrolls can be displayed by multiple screens with the same content.  There's probably ways I can improve on it though, and I still have no idea what the differences between public-vs-protected or internal-vs-private are.  Something useful I'm sure.  I also didn't figure out how to reference TCODKeys directly instead of interpretively.


So anyway, I wanted to show up tonight with a big "look at my awesome placeholder interface" post.  On top of getting a little waylaid, I also decided that the time that it would take me to make a placeholder interface just to show off and then scrap would be better spent on actual important shit.  That didn't take good screenshots though, so I'll probably be spending this week doing some of both.  The important shit in question being an Action controller, so things that need to happen can be scheduled to fire off when the game's internal clock ticks around.  It's probably more important that I make something like a basic world generator first, but I'm kinda developing my code in a couple different projects so I can prototype different ideas independently of each other.

I'm also looking down the road at a serious issue that I'm more than open to advice on (and not just from you Max).  That is: saving the game.  Except for writing a human-interpretable textfile containing instructions on how to rebuild all of the objects in memory, I have no fucking clue how other games actually save their data and then read it back in.  Is there some kind of "memory dump" option in C#, so it can make a savestate of the program that a person couldn't load into Notepad and edit by eyeball?
Logged
And here is where my beef pops up like a looming awkward boner.
Please amplify your relaxed states.
Quote from: PTTG??
The ancients built these quote pyramids to forever store vast quantities of rage.

GalenEvil

  • Bay Watcher
    • View Profile
    • Mac-Man Games
Re: Aqizzar Finally Starts Making A Game
« Reply #39 on: February 11, 2013, 01:03:08 am »

RE: "Memory dump": You can use a binary serializer to deal with most of the code stuffs. Strings you might need to obfuscate somewhat though since those would probably get pushed through as plain text. As an added measure you could take the binary data and bitshift, or apply a "NOT filter", it a little to obfuscate, and just shift it in reverse during the deserialization process before reading it back in as object data. There are a lot of ways to deal with serializing the data that keeps it easily translatable back into a usable state :D
Logged
Fun is Fun......Done is Done... or is that Done is !!FUN!!?
Quote from: Mr Frog
Digging's a lot like surgery, see -- you grab the sharp thing and then drive the sharp end of the sharp thing in as hard as you can and then stuff goes flying and then stuff falls out and then there's a big hole and you're done. I kinda wish there was more screaming, but rocks don't hurt so I guess it can't be helped.

Max White

  • Bay Watcher
  • Still not hollowed!
    • View Profile
Re: Aqizzar Finally Starts Making A Game
« Reply #40 on: February 11, 2013, 01:07:35 am »

Well what ever works for you. We all have our own habits that we get used to.
The version that I put up is actually a little watered down from what I normally do, just to make life easy for people slightly newer to programming, but I always over do what ever I can.

And yea, C# has class extenders. I don't know of their existence in any other language, but hopefully they will become a little more popular.

I won't have time to write anything up right now, but as for saving and loading data, you will need to look up Serialization and a reader/writer. The FileStream class works, but there are other options. Unlike Libtcod, there is some great documentation on this stuff out there. To my understanding there is no way to just save the state of an entire program that couldn't be modified, but at least if you save in a binary format, rather than a string format, it would be very, very hard to edit without having access to your source code to reverse engineer the saving/loading procedure.

Also, how did you go on the 'Mapping char to libtcod value' problem? I found the easiest solution was to just use the .print function rather than .setChar.

Aqizzar

  • Bay Watcher
  • There is no 'U'.
    • View Profile
Re: Aqizzar Finally Starts Making A Game
« Reply #41 on: February 11, 2013, 01:27:00 am »

Also, how did you go on the 'Mapping char to libtcod value' problem? I found the easiest solution was to just use the .print function rather than .setChar.

...Uh, I wrote a bigass switch statement to translate Unicode characters into bytes and then send those to Libtcod.  This is unfortunately crippled by Libtcod's default terminal graphic being a bit different from the Codepage 437 standard, but I think I can live with the various box-border tiles being replaced with more vowel-alterations.  I haven't looked into .print versus .setChar, but since this whole project is intended to be an experiment instead of a fully-featured game, I'm not overly concerned about everything being as good as it could be.

As for the saving/loading, I'm not specifically worried about data security or anything, I just wanted something less cheesy than spitting out textfiles full of DF-raw style information tags that would be written/read by an interpreter function.  If there's a way to serialize an object's data for output, and then read that serialized data back in to rebuild the program's active objects as it was, then that's exactly what I'm looking for.
Logged
And here is where my beef pops up like a looming awkward boner.
Please amplify your relaxed states.
Quote from: PTTG??
The ancients built these quote pyramids to forever store vast quantities of rage.

GlyphGryph

  • Bay Watcher
    • View Profile
Re: Aqizzar Finally Starts Making A Game
« Reply #42 on: February 11, 2013, 01:39:16 am »

And yea, C# has class extenders. I don't know of their existence in any other language, but hopefully they will become a little more popular.
I honestly thought this was a basic and common language feature. o_o I mean, I know not every language has it working completely (not every language fully supports lamdas either, C++ didn't until the most recent version), but I thought it was one of those things you generally expected and then were upset to discover they'd botched it up in the rare cases it was missing.
Logged

Skyrunner

  • Bay Watcher
  • ?!?!
    • View Profile
    • Portfolio
Re: Aqizzar Finally Starts Making A Game
« Reply #43 on: February 11, 2013, 01:49:15 am »

I always thought that it would be logical to have such a thing, but alas!
Logged

bay12 lower boards IRC:irc.darkmyst.org @ #bay12lb
"Oh, they never lie. They dissemble, evade, prevaricate, confoud, confuse, distract, obscure, subtly misrepresent and willfully misunderstand with what often appears to be a positively gleeful relish ... but they never lie" -- Look To Windward

Max White

  • Bay Watcher
  • Still not hollowed!
    • View Profile
Re: Aqizzar Finally Starts Making A Game
« Reply #44 on: February 11, 2013, 06:29:10 pm »

So all things considered, this might not be that much help to you Aqizzar, but last night I actually put together that tutorial I posted into a dll to make things simple. I'm sure somebody out there will be happy with it.

RogueBase - Simple dll that is full dependent on libtcod to run, but all required files included for you.
GobKill - A game I made in about 20 minutes that gives an example of how to use RogueBase. Also includes a quick demonstration of how to use the noise function that comes with libtcod.

I can't endorse the game logic used in GobKill. It was made in the time it takes to drink a cup of tea, so don't expect great structure, but the way it uses the base is fine.

Legal junk: Anybody can do what ever the heck they want with it, commercial or otherwise. Don't even bother to credit me if you don't want to. I mean I wouldn't be upset if you did, I just really don't care. Have fun with it!
Pages: 1 2 [3] 4 5 ... 10