Jump to content
  • Advertisement
Sign in to follow this  
  • entries
    122
  • comments
    121
  • views
    69242

About this blog

My not-so daily posts on my current console project

Entries in this blog

 

Wrapping world display

I just finished adding a wrap-around functionality to World::Draw(), with a boolean parameter to enable it. It was actually a lot simpler than I thought it would be. In the previous version, without wrapping support, I had to clip the SMALL_RECT parameter entirely down to [0, width) and [0, height). In this version, I put the clipping code in an if-statement, only to be run if the wrap flag is false. Within the loops that map each World buffer index to a temporary buffer, I calculate the indexes with modulo, and if it's a negative result, I subtract it from width/height (because it's already floored down to that range). Here's the final code:


BOOL World::Draw(SMALL_RECT& clip, COORD drawloc, bool wrap) const
{
if (clip.Left > clip.Right || clip.Top > clip.Bottom)
throw std::exception("Bottom/Right cannot be greater than Top/Left!");

if (!wrap)
{
if (clip.Left 0) clip.Left = 0;
if (clip.Top 0) clip.Top = 0;
if (clip.Right >= width) clip.Right = width - 1;
if (clip.Bottom >= height) clip.Bottom = height - 1;
}

int view_width = (clip.Right - clip.Left + 1), view_height = (clip.Bottom - clip.Top + 1);

if (view_width == 0 || view_height == 0)
throw std::exception("Viewing dimensions too small.");

CHAR_INFO* buf = new CHAR_INFO[view_width*view_height];

for (int y = 0; y {
for (int x = 0; x {
int world_x = (x + clip.Left) % width,
world_y = (y + clip.Top) % height;

if (world_x 0) world_x += width;
if (world_y 0) world_y += height;

buf[x+(y*view_width)].Attributes = buffer[world_x+(world_y*width)].Attributes;
buf[x+(y*view_width)].Char = buffer[world_x+(world_y*width)].Char;
}
}

SMALL_RECT writeloc = {drawloc.X, drawloc.Y, view_width+drawloc.X-1, view_height+drawloc.Y-1};
COORD bufsize = {view_width, view_height};
COORD origin = {0, 0};

BOOL retval = WriteConsoleOutput(screen, buf, bufsize, origin, &writeloc);
delete buf;
return retval;
}






I also noticed this time around that I had a memory leak on the last line. Originally I was just returning the return value of WriteConsoleOutput(), but I had completely forgotten to delete[] the temporary buffer I passed to it. The last three lines here solved that.

So it wasn't nearly as hard as I thought it would be. Awesome!

~Jonathan

Twisol

Twisol

 

Wow, this is fun

I made a sort of cin-esque function, except it's specifically for console-buffer type applications like mine. I'm using it in the actual project to have the player input a character name. The kewl thing about it is, not only can you set what keys you want to use (as usual), you can also set precisely where you want the input to appear at.

I'm gonna update my project progress list above my journal, and for future information, 'green' means it's done, and 'lightgreen' means it's practically perfect in my eyes. :D

Twisol

Twisol

 

World::View

Today (and partially last night) I wrote up a View class to wrap the clipped view of the World returned by World::DrawView(). It's constructible only by World (excepting the copy-ctor, which is public), taking width and height parameters to create a dynamically-allocated CHAR_INFO buffer. It overloads the [] operator and a conversion operator (because it was easy and it makes sense), and handles the buffer's memory itself.


class View
{
private:
CHAR_INFO* view;
int width, height;

View(int width, int height);
friend const View World::DrawView(int, int, int, int) const;
public:
View(const View& v);
~View();

View& operator=(const View& v);
CHAR_INFO* const operator[] (int idx);
operator const CHAR_INFO* const() const;

int Width() const;
int Height() const;
};




This is all I need to do to draw my world view to the screen:

void Game::Draw()
{
World::View worldview = world.DrawView(0, 0, world.Width(), world.Height());
SMALL_RECT drawRect = {0, 3, worldview.Width()-1, worldview.Height()+2};
COORD origin = {0, 0};
COORD worldsize = {worldview.Width(), worldview.Height()};

WriteConsoleOutput(hOut, worldview, worldsize, origin, &drawRect);
}

Notice that I can pass worldview to WriteConsoleOutput? That's the conversion operator (converts to const CHAR_INFO* const). I think it looks really clean. DrawView() takes the xy coordinates of the upper-left and lower-right rectangle to view. Technically, passing the world's Width and Height puts the rect one over the edge on the right and bottom sides, but DrawView clips it down, so it's a small shortcut rather than subtracting one from each. Then again, I have to do it in the drawRect anyways...

Twisol

Twisol

 

World view and map generation

Don't get all excited, I haven't gotten all that far from where I was last night. I've been working on the world view (typename changed from WorldView to World) and I think I have a far better design for it than last time. The World is constructed with a world width and height, and it doesn't care in the least what part is viewable. I think that makes more sense anyways.

World also has a DrawView method that takes the width and height of a viewing window, and the upper-left coordinate of the area to be displayed. It currently returns a CHAR_INFO pointer to a dynamically-allocated buffer, but I don't like having 'new' in one class and 'delete' in a whole different one, so I might be wrapping it into a new WorldView class representing the viewing area, with the new and delete calls both in the same logical area. Comments on that idea would be welcome.

Now, about the map generation bit. I replayed the Snipes game, downloaded from here if I didn't post that already, and I've come to the conclusion that the maze is randomly generated each run. I think I'm actually excited about that... but I really, really want to get the core elements in first.

One thing I'm not quite so keen on is the collision detection, although I think it was so horrendous before because of bad design. But yeah... back to World coding.

~Jonathan


EDIT: I can't speak for the rest of Win32 - I've never used it in depth - but Microsoft did a great job on the console functions. I just found [Get|Set]ConsoleCursorInfo functions, easily removing the annoying blinking cursor from the screen. I'm being careful to save the original values of things like the title and the cursor settings, so I can return them to normal when the program is finished. I'm not honestly sure what would happen if I left them like that when the program finished, and I had run it from cmd.exe myself.

Twisol

Twisol

 

WinMUD, SVN, and XP, oh my!

Technically WinMUD is not a MUD, but its the name I gave it when I started, so I'm sticking with it.

Anyways, I've decided to change my to-do list to reflect changed to WinMUD instead of Arenamatic, since the only part of Arenamatic I was really looking forward to (and pleased with) was cConsole. Take a look. [grin]

I've finished, for the most part, the Roomset component. It's fairly well-known, or at least I thought it was, that a MUD or similar game is made of three parts: rooms, connections, and entities. And, duh, functionality, but I'm talking about actual parts. So far I have the rooms and connections finished, and I'm working on entities. Now, that doesn't mean I'm almost done; no, I still have the command parser after that, and then I'll have to figure some way of linking (not the compile-and-link sort) them together.

In other news, I got an SVN up. Sooner or later I'll get a link up to it; make it easy for you to look at my progress. I'll be committing my changes every time I get something right, which might be a couple times a day, so when I get the SVN up, watch it. [wink]

Also, I set up a new WinXP account exclusively for my programming stuff. I've named it ProGamer RM, kudos to anyone who can figure out why. (if no-one guesses, or comments, I'll say what it is in the next entry)

Gonna work a bit more tonight then head to bed.

Twisol

Twisol

 

War!

War is coming along well. I have the basic Card and CardDeck classes, with CardHand on its way. I'm also working on the War class, which will handle most of the details of the gameplay. When it's used, you simply create an instance of War, specifying with a bool whether to include Jokers or not, and then run a while loop that iterates over War::Fight() and War::Draw().

Making the two steps of the game into two functions allows the user to do additional stuff between the draw and the fight, such as wait for user input before doing either. Also, a built-in safeguard prevents more than one draw in a row, as well as more than one fight in a row. As well, Fight() handles the details of the "War round". Draw() returns whether the cards were drawn at all (in case someone's deck is out), and Fight() returns the result of the battle (1 if you won, 2 if the opponent won, and 0 if it was a war).

How does the user figure out whether there will be a War round before it occurs? The GetPCard() and GetOCard() methods return the Card that the Player or the Opponent, respectively, will be playing next turn. They returns BAD_SUIT, BAD_VALUE cards if there was no Draw() after the last Fight(), or if the one player has no cards left. This effectively also lets the user know whether one player has won, as there will never be a winning game with both players having empty decks, nor will there be a case where only one deck is drawn from. (I'm sure I could implement a helper Won() function if I think it's required...)

I'm debating over whether to add GetPSize and GetOSize methods, because that would take away from the value of the Get[X]Card methods being able to tell you if there was a winner, although it would make it easier.

Anyways, thoughts on my progress?

Twisol

Twisol

 

W00T

I've finished the shop interface (other than the actual buying stuff), and it's really awesome, in my [very humble] opinion. I've uploaded the code + exe, and you can get it from the link below my to-do list (which I've also updated). Please take a look, and let me know what you think!

Comments on code structure would be great, as long as they don't blatantly say "This is totally wrong, dump it and do this instead". [grin]

EDIT: I said 'jump' instead of 'dump'. [tears]

Twisol

Twisol

 

Verrrry short hiatus from Cripes! 2.0

I have a few non-hobby projects I need to devote my time to, so I'm going to focus on those and get them out of the way. Consequently, Cripes! is going to be a little sluggish for the next week or so.

Books
I got three new books today! No, the GameDev.net book will get here Thursday, but I went to Borders and got some really good programming books. The first, Core Web Application Development with PHP and MySQL, is really, really in depth, covering a variety of pertinent subjects such as classes in PHP (which I've been interested in) and security. I looked at pretty much every PHP book at the store, and this book - though I've only read one chapter right now - looked a lot better than the rest.

The next book I got was Head First: Design Patterns. I wanted a book on design patterns, and I like the Head First series... though it helped that there weren't any other design pattern books, heh. The third book is Sams Teach Yourself Ajax, javascript and PHP, which I got for the same reasons I got book number one: web development. I've never, ever done anything with Ajax or javascript, so I don't feel bad getting a more basic volume.

MusicShake
I've done three other tracks using the MusicShake software since I last posted! I can't seem to extend them very far over two minutes, but I kind of like leaving them short, so...
Atmosphere (01:47)
Flight Over the Ocean (02:29) -- Please excuse the corny title!
Escape Velocity (02:03)
Crystal Music Box (01:47)
Enjoy! [smile] And comments wouldn't hurt either. [wink]
~Jonathan

Twisol

Twisol

 

Vacation

I'm going on vacation for two weeks in Florida! I'll be staying right by the east coast, and there's a cute girl living right across the street. [gasp] If I'm lucky, I might be able to work on some Lua while I'm there, but C++ is probably not going to happen. I tried to get a USB flash drive (2GB) today, but we didn't have time, so I'll have to grab one tomorrow if possible, but that's when we're leaving. I guess I'll just download lua and luac when I get there.

As for the airplane trip, I bought a magazine, four Dragonlance novels, and a book on applying mathematical concepts to game programming. I'm going to go through it all by the time we arrive in Florida...

Oh, does anyone know if it's possible to get your GDnet username changed?

Twisol

Twisol

 

Username Change

So, for those of you wondering who in the world Twisol is and why his journal is on your bookmarks - nevermind that linkofazeroth's journal is gone, it was never very interesting - I had a namechange from linkofazeroth to Twisol. Feel free to ask why, you know, anything to get a few comments around here. What are you, comment misers? Sheesh.

There really hasn't been too much of an update since last time. I'm adding support into the GameView for actually using entities though, and changing the HUD like I mentioned last time. I'm afraid to post any screenies too, because the only difference between the last two WAS A GREEN X. Sad...

Twisol

Twisol

 

User Input Hassles

I'm not actually sure how to proceed here. User input is easy enough on its own, but I need to continually Draw() at a certain framerate as well as watch for user input (and act on it wen it comes in). I created a Keyboard class, but I'm really not sure how to do this.

I want to draw, at the moment, once every 0.25 seconds. I also want to watch for user input constantly, and move the "camera" every time a key is pressed (but only allow them to move once every so often). And I don't want to continually loop, because I think that hogs CPU; I just want to do something if there's something to do, or it's time to draw.

The only thing I've managed to do, that works in some respect, checks the console input buffer every time through the loop and sets the appropriate element in an array of bools depending on what key event comes through. Then it draws, and Draw() checks the time elapsed between the last time we drew and now, and if we're good to go, it checks the arrow key booleans and moves accordingly. The problem here is that it only works if we held the key down when Draw() actually draws. If we hit an arrow key after 50ms since the last Draw(), and let go at 100ms since the last draw, it's like we never hit the key at all - Draw() doesn't recognize that we tried to move. And it keeps looping whether we have anything to do or not.

Obviously I'm new to handling keyboard input like this. I think WaitForMultipleObjects() could help (because it can wait on an input buffer handle), but I still have no idea how to proceed. A poke in the right direction would be hugely appreciated! =\
~Jonathan

Twisol

Twisol

 

USC, SAT, WTF OMG BBQ!

My family and I did a Meet USC program yesterday. USC is the University of Southern California, and their Meet USC program is basically a three-hour tour, where the last hour includes talking with the admissions person at a specific school within the university. A little backstory before I go further:

For the longest time, I've wanted to go to Digipen. Sure, no problem, right? Well, a few weeks ago I stumbled across an article on Josh Petrie's blog - yes, that jpetrie - that weighed trade schools like Digipen against traditional universities. A whole lot of what he said made sense to me, and he had even gone to Digipen himself. So going along with the article, I decided to see what my options were.

Ironically - or perhaps poetically just? - the first university I saw was USC. I read up on it and it really looked like just what I wanted. I even managed to talk with an alumnus - on #gamedev no less! - and got his opinion on it. Better, they have a Computer Science degree with an emphasis on Games. It's still a CS degree, meaning I'm not really going for one of those game development degrees so many people have told me to stay away from... like Digipen's. Now, that is irony.

Fast forward to yesterday's Meet USC tour (which I signed up for about a week or so beforehand). It started with a presentation by two peple, one who was going to be a senior next semester and was double majoring, did overseas study, et cetera. The other was an admissions person for the university. They said some stuff about USC, went over applications, and other stuff. Did you know they have over 600 clubs at USC? Yeah. One of them was founded by Will Ferrel while he was there; it's called the Lizard Lovers. The admissions person also told us - oh, did I mention, we weren't the only ones at the Meet USC tour? :P - about an applicant who, when answering an "Explain yourself in three words" question, wrote "A sexy beast".

For the second hour we walked around the campus with a goofy, but nice and informative tour guide. Not much I remember about that hour, although that's when I learned the bit about Will Ferrel's club.

During the third hour, the group got split up according to the studies they wanted to do. We went with the Architecture and Engineering group because the Viterbi School of Engineering is the one that runs the Computer Science (Games) program. A guy who worked there sat down with us (only four of the original group were interested in Engineering) and talked with us about how things would work relevant to the Engineering classes. A lot of good information all around, but by then I was getting hungry. ;P

I absolutely enjoyed the Meet USC tour, and I've definitely decided that this is the university I want to go to. Yaay. :D

Now on to the next acronym. I have to take my SAT and some SAT Subject tests in order to apply. I already downloaded and did some of the SAT Practice Test, but I'm not sure I'm absolutely prepared for the actual test. But I have until October before the next SAT will be held, which is good. I bought an SAT study book from those Kaplan study book people today, and I'm having it shipped in 3-4 business days, so it should be here relatively soon.


Now, after my rambling about college and testing, I'm sure you want to hear more about Cripes. Right? Right? No? Too bad. I've made some changes to how I catch and handle input events, so I can handle mouse and keyboard events simultaneously. It's slightly reminiscient of the typical windows message loop with GetMessage/PeekMessage, which is, in my opinion, a Good Thing.

I'm also slightly surprised at how easy it was to set up simple HUD and GameView windows in the console, but that's kind of the point, anyways. I'll be using the HUD to display the characters and colors you can click to select. I might even make a small menubar at the top to easily load and save maps, and other things like that.


Alright, have fun reading all of that. And as always, comment nao!!

Twisol

Twisol

 

Updates

First of all, thanks to Programmer16 for his suggestion that I let getKey() take the keys as a parameter instead of just reading the string off of cConsole. I might as well get rid of the 'keys' string now since it's redundant. Thanks P16!

The character creation stuff is nearly done, just have to add in the formula for getting the health of the player. I experimented with making a console.conArt() function that would take some collection of hexadecimal color codes (like how I use output()), a length, a width, and a point in the buffer to start outputting the semi-ASCII art. Well, it was far too difficult to code, so I'm dropping that idea.

After I finish with removing 'keys' and adding the health formula in character creation, I'm moving on to the store. I'll probably have to add "int armor" and "int weapon[3]"; into the cChar class (what I use to hold the player's data). 'armor' basically holds an integer which "means" some unique defence bonus. 'weapon' holds three values: the attack bonus of the weapon, the battle roll(s) needed to count a critical strike, and the critical strike modifier (2 or 3), which means how many more times the attack hits to count for the crit.

Oi. I think I might just make a class "armor" and a class "weapon" to hold these values, then do "player.armor = new armor" or something like that. Seems a bit easier on the brain.

Comments welcome. :)

Twisol

Twisol

 

Update so far

I finished task two of my to-do list today, so now my HUD's data is all stored in files for easy modification. I have the single lines of info (like "Score" and the smiley face characters) in "statics.txt", and the actual data in "layout.txt". The format for the statics is one static per line, in the form "".

For the layout file, things are a little different, because there's a specific number of data items that the game needs to place. There's nine data fields on the HUD, so there has to be a corresponding line for each. The format is just like the statics.txt, but in the form "".

In the end, a chunk of code for laying out the HUD has been taken out. Yay clean code. I think I'm going to work on the timer class next...

(I haven't had comments in ages! A simple "hey, looks good" would be nice XD)

Twisol

Twisol

 

Ugh

After a couple MASSIVE headaches on the issue, I finally managed to templatize the store. I'll just have to add some way of adding items in, probably with file I/O. Then I can test the store again... and finally upload a new version of the Arenamatic. Thanks to jpetrie on #gamedev for helping me out!

Twisol

Twisol

 

Twitter, and Cripes 2.0: World change

I caved in and signed up on Twitter. [rolleyes] I don't know how much I'll use it, but I like how EasilyConfused uses his, so... I also downloaded Spaz to use to update myself. Maybe it'll be easier to keep this going that way. [lol] My twitter link is http://www.twitter.com/twisol, if anyone wants to follow it.

I also mucked with World like I said I might last time, cutting out the Map class and merging EntityMap into World. It definitely feels a bit cleaner. It makes it easier to provide my Strategies with a context, too, so the Entity can test for collision against another entity. I'm still working on how that'll happen, though. Still, things feel like they're shaping up.

Ideally, I don't want to have anything worry about what kind of Entity an Entity is (i.e. Bullet) except the Entity itself and its Strategy. Entity already inherits from IDrawable, so World knows it can draw it (and doesn't need to know anything else). Like I said, I'm working out how exactly the whole Strategy thing will work, but in the end, Entities will really just be treated as Entities or IDrawables, and nothing else.

~Jonathan

Twisol

Twisol

 

Tough

Project 2 of the C++ workshop was unveiled.. I'm going to have to work hard to get that done. It really looks tough.. meaning, I've never done something as big as that before. Big being relative to what I have done before.

On other news, I've uploaded the [at the time] current versions of cConsole, my console-manipulation class (done but not polished, as the todo list states), and the source code and executable for "Consolian Arenamatic", my program for Project 1 of the C++ Workshop. Check the to-do list for details.

I've done away with the 'keys' string in cConsole I mentioned, and I'm working on the store. I've added two classes, armor and weapon, to hold the values for current armor and weapon ("*player.equip[0] = new armor", for example, though 'equip' isn't in player.h in the uploaded .zip), and now I just have to work on the store itself, and buying stuffs. Yay. Then I go on to the arena.

Hmm. Does anyone even read this, besides Programmer16? If you do, please comment... I feel all alone. [sad]

EDIT: I just realized the .zip had a VERY old version of the .exe! Oops! [tears]

Twisol

Twisol

 

Today's AreBat update

AreBat is pronounced ah-REE-bat, and stands for Arena Battle. :P

Well, today I chatted on IRC way too much. I did take out a useless string (and its functions) in the cArena class, though, as well as change the way I utilize my modes in the actual program. I'm making sure my store class works the way I want it to by using it to implement a store into the arena program. If I can't do it, or have an insanely difficult time doing it (stupidity doesn't count), I'll incorporate functionality for whatever was annoying into the class itself.

Hopefully tonight I can green out one of the to-do list items, and notch the title from orange to yellow. [grin]

EDIT: Ok, sadly I will not be able to say that my store is done. I'm having troubles... runtime troubles... with my tests. Le sigh. Gotta prove that it works and can be done before I can green it. [sad]

Twisol

Twisol

 

title*

Yeah, I haven't posted in a while. I have a good reason, though! I got selected for the World of Warcraft expansion beta for Burning Crusade. [cool]

In Arenamatic news, the shop's done and working, but I had the idea of adding my scrolling list feature to the actual console class so it can be reused again and again. It's a good idea, no? [grin]


*The subject should properly be >_>, but the subject bar doesn't like it.

Twisol

Twisol

 

TinyXML

Well, Deranged has pointed me to TinyXML, so I might just scrap the current file parser I'm working on. It depends on if I can use TinyXML to fill instances of class "item" with the information parsed from an XML file. Could anyone reading this comment and let me know if it's possible and a good idea to use TinyXML to parse an XML file like below (this is just a guess at what an XML file would look like, I don't have any experience with XML) into a C++ object like [also] below?

EDIT: Hah, the past three entries have started with "Well". Ironic, since I'm not feeling at all "well" right now!



"Mana Potion">
A potion of Mana

+10

10
5
1






class item {
string name;
int price;
string desc;
mapint> effects;
int InvenQuant, EquipQuant, StoreQuant;
}



Twisol

Twisol

 

Timers

Tonight I worked through my implementation of "timers" a little bit, and fleshed out how I want the game to run a little more. My "delay" techinque, quite simply, was restrictive. Luckily, I found out about the SetTimer function. I had to rework the main loop of my program (as seen in my last journal entry), but I think it was definitely worth it.

My current approach leaves the keypress checking to the main loop, and moves the actual HUD updates to a TimerProc function. I have to create a timer with SetTimer and pass it the address of TimerProc, so during my main loop I also check for messages, and translate/dispatch the WM_TIMER messages. Dispatching the WM_TIMER message, if it was caused by the timer I created, will call TimerProc!

Below is my new and improved main() function, as well as my current TimerProc function.


void CALLBACK TimerProc(HWND hWnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
{
static bool timestatinc = false;
//Because this function is called every 500ms, I need to keep track
//of whena full second has passed. Only then do I update the time data.

if (timestatinc)
++GameInfo.time;

GameInfo.score += 10;

hud.Draw(0, 0);

timestatinc = !timestatinc;
}

int main()
{
Init();
hud.Draw(0, 0);

if (!SetTimer(NULL, 1, 500, &TimerProc))
return 1;

while (true)
{
int vkey = CheckForKeypress();
if (vkey == VK_ESCAPE)
break;

MSG msg;

if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
if (msg.message == WM_TIMER)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
}

KillTimer(NULL, 1);
}





I'm still not sure what the commenters meant in my last post, but I'm pretty sure this approach will be sufficient for Cripes!. Thanks for the input though, always great to have! *hint hint*


EDIT: In other news, my grandmother let me pick out and buy three books, which totalled to $140 total. I know, it's mean for me to do that, but she let me AND she said it would be an early birthday present. "As long as you read them and learn from them, I'm fine!" So, yeah. I'm now the proud-to-semi-proud owner of World of Warcraft Programming (addons and such), Breaking Into the Game Industry (my favorite so far!), and Windows From C/C++ (at $70, I should like this best, but... I don't. It's handy though, and I got the SetTimer idea from it!)

Twisol

Twisol

 

Timed stuffs!

First, a thanks to EasilyConfused for his much appreciated comment. :D

Today I coded in a timed delay thing into the game's main loop. This way things don't go lightning-fast on the player... it's limited to doing stuff once every 500 miliseconds now. I guess you could call each interval the game does stuff in a "frame", yes? I also added a keyboard input function, to check if there was a valid keypress, and return its virtual key identifier (for example, VK_ESCAPE)

Here's my main() function, to show you how the main loop looks so far. I think I just need to work on the actual gameplay now...


int main()
{
Init(); // Sets up the HUD details and console title

bool quit = false;
int timestat = 0; // Because each frame is half a second, I need
// a way to know when to increment the HUD's time
// field - that is, once every two frames.

while (!quit)
{
unsigned long currtime = GetTickCount();
hud.Draw(0, 0); // The arguments specify the x,y coord of the
// top-left corner of the HUD.

GameInfo.score += 10;

if (timestat == 0) timestat = 1;
else if (timestat == 1) { timestat = 0; GameInfo.time += 1; }

// During the delay time, when nothing is being done, I watch for
// keypresses. I used to have it outside the while, but there was
// a visible delay between pressing and exiting when the key was
// pressed after the check and during the delay. Placing it in the
// loop lets me check as many times as the while iterates per frame,
// and because the game doesn't take long to process what I have so
// far, there's no visible delay in quitting.

while (currtime+500 > GetTickCount())
if (CheckForKeypress() == VK_ESCAPE)
{
quit = true;
break;
}
}
}




EDIT: If you're wondering, and I'm sure you are, the game looks no different now than a month ago. The only differences are internal, except that I'm actually displaying the game's data in the HUD, not just the "static" lines. Nothing new though, just zeroes! (Although I use a line of six zeroes as a static to the right of the Score line, so it looks like we've got a sort of zerofilled score going on when the score is drawn on top of it. I likey.)

Twisol

Twisol

 

The Programming Squib

Heh, yeah, I feel like a squib right now.*

I've been feeeling a little, eh... stagnant with my programming lately, mostly because I haven't been able to properly complete a project. ((Yes, I realize many of you haven't either :D)) So I bought the GameTutorials set of tutorials... so far I think I've made a worthwhile investment.

I ran through the early C++ tutorials really fast just to make sure I knew what I needed, and I eventually got to some Win32 console stuff, like what I had been doing with cConsole before. One tutorial that caught my eye was "Color Text"... I glanced over it, and behold, text coloring in the console that was far simpler than what cConsole attempted. I really was floundering back there, ugh.

So I ran through the tutorial code, tweaked it, and got rid of the positioning code; I didn't feel I needed it at that point. What I got worked well enough: two functions, ColorPrint and ColorPrintln, that took a text string and a color value. I found I was passing the same color value repeatedly, and besides that it looked really monotonous and klutzy. So I tried something I haven't tried before: I made an iostream manipulator, to use with std::cout.

At first I had the most basic of manips:

class color
{
private:
ConsoleColor myColor; // This is just an enum of colors I made.
public:
color(ConsoleColor theColor)
: myColor(theColor)
{}

void operator()()
{
HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleTextAttribute(hOut, myColor);
}
};

ostream& operator{
theColor();
return out;
}




I liked this solution a lot better than the functions I had made before. All you needed to do was creat the manip and pass it to cout. Like most manipulators that I've seen, all you need to do is this:


cout

Easy and intuitive, especially because you're using cout there instead of through a function. A few slight gripes I have are that the manipulator does not actually change the state of cout... it changes the attributes of the console itself. This will be important later! For this reason, the operator() doesn't require any parameters, nor does it return anything. The operator
Well, me being me, that wasn't enough. I took the positioning code from before and made it into its own manip. All it does is set where the console caret is... thus, again, it does nothing to the ostream itself, only the console. Again, this will be important later!

Further, foreground text coloring isn't the only coloring you can do with the console; you can also color the background of the character cells. I thus renamed the color manip into 'forecolor', and created the 'backcolor' manip, which looked exactly like forecolor, but bitshifted the color value
The backcolor manip worked just as well as the forecolor manip did... except that they didn't take eachother into account. Do you see the problem? If the console text attributes already had a foreground, if I called the backcolor manip, it replaced the entire mask with the lone background color. Obviously, that's not good, especially because color values are not the only values held in that mask.

In short (yeah, like anything about this post was short!), I called GetConsoleScreenBufferInfo() for the screen buffer info struct, took the attributes mask out (which is of the WORD type), and did some binary ORs and ANDs. The formula I used to retain the original mask, but replace the value I wanted with the forecolor, is ((theMask & 0xFFF0) | myColor). I AND out the part I want to remove, but retain the rest, and OR in the new value! This fixed my mask problem.

Here's the code for the color manips, with inheritance included. Feel free to use it!

CONCOL.H (CONsole COLor)

#include
#include

enum ConsoleColor { CC_BLACK = 0, CC_BLUE, CC_GREEN, CC_CYAN,
CC_RED, CC_PURPLE, CC_YELLOW, CC_WHITE,
CCI_BLUE = 9, CCI_GREEN, CCI_CYAN, CCI_RED,
CCI_PURPLE, CCI_YELLOW, CCI_WHITE};

class color
{
protected:
ConsoleColor myColor;
public:
color(ConsoleColor theColor);
virtual void operator()() = 0;
};

class forecolor : public color
{
public:
forecolor(ConsoleColor theColor);
void operator()();
};

class backcolor : public color
{
public:
backcolor(ConsoleColor theColor);
void operator()();
};

std::ostream& operator




CONCOL.CPP

#include "concol.h"

color::color(ConsoleColor theColor)
: myColor(theColor)
{}

forecolor::forecolor(ConsoleColor theColor)
: color(theColor)
{}

backcolor::backcolor(ConsoleColor theColor)
: color(theColor)
{}

void forecolor::operator()()
{
HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);

CONSOLE_SCREEN_BUFFER_INFO* csbi = new CONSOLE_SCREEN_BUFFER_INFO;
GetConsoleScreenBufferInfo(hOut, csbi);

SetConsoleTextAttribute(hOut, ((csbi->wAttributes & 0xFFF0) | myColor));
delete csbi;
}

void backcolor::operator()()
{
HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);

CONSOLE_SCREEN_BUFFER_INFO* csbi = new CONSOLE_SCREEN_BUFFER_INFO;
GetConsoleScreenBufferInfo(hOut, csbi);

SetConsoleTextAttribute(hOut, ((csbi->wAttributes & 0xFF0F) | (myColor 4)));
delete csbi;
}

std::ostream& operator{
theColor();
return out;
}




There it is. Now, remember how the manips affect the console, NOT cout? This is important, and I'll explain why. When you use one of the color manips, for example, it sets the state of the console to put characters in that color scheme from that point on. This includes input typed via cin. Wow, who would have guessed? Ah, well, like I said, the color manips don't touch cout anyways. They're not exactly your usual manips. This means that you can have the user enter input in a different color. That's pretty neat, isn't it? It works the same for the position manip, even though I haven't put the code up here. Once you set the caret position, cout and cin work from there.

So... pointers, ideas, criticism, and of course colored input are all welcome!

~Jonathan

EDIT: And of course, I forgot to mention! Because both manips are derived from the virtual class 'color', only one operator>> is needed, because it can take a reference to an object of type color. Handy!



* Oh yeah, about the squib comment. In Harry Potter, Mr. Filch the caretaker is a Squib, meaning a wizard-born who's barely got a drop of magic in their blood. A programmer squib, thus, should be obvious. To take the analogy further, compare GameTutorials to Kwikspell, and there you have it.

Twisol

Twisol

 

The moon

I guess the Portuguese actually don't see the same moon as the rest of us. Seems they just see a big ball of code in the sky.

Ahem.
And for those people who actually comment here, I might just try SDL after I get a handle on the Lua basics. I kind of want to work on a simple text game before I go into graphics.

Twisol

Twisol

 

The Cow jumped over the Moon

About the title: My math teacher was discussing the origins of the name Lua (Portuguese for Moon), and since Lua is Luna minus the N, he said "Well, Moon minus the N is Moo."

Anyways, with Programmer16's help, I found a tutorial that's up to date with Lua 5.1, so YAY, I've got Lua working. Now I've got to experiment with calls between Lua and C++ (making a calculator as a test project), and then I'll try integrating into Harbinger (that's not for a bit though).

To Programmer16: I was away today, wasn't home at 5 EST, sorry.

Twisol

Twisol

Sign in to follow this  
  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!