Wednesday, February 23, 2011

Google vs Bing

As a computer instructor, I am often asked why I prefer Google over Yahoo or Microsoft's search engine (whatever they are calling it this year).  80% of the world uses Google, which can be a little scary to think about.  It would be so easy for them to abuse their power.  I will be the first to admit that they have gotten a little less cool in the last five years, and I wish they had an advanced version that had less hand-holding and would let me just get on with my searches, but even with all that, Google is miles above their competition in a few key areas.  (I'm not going to really talk about Yahoo here, they have about the same market share as Microsoft, but they have too many ads and they don't try very hard to make their search better than any one else's)

No matter how "evil" Google gets, rest assured that Microsoft has done worse.  I should give some of Microsoft's history on here sometime, that would be fun.  Let's just say that you don't get to the top of the Business software game by being nice.

Google still has a sense of humor, although it's been getting dimmer over the years, and their April fools jokes are more about highlighting their newest product than having fun, and the Google Doodles are more about public relations than about celebration.  But, compared to any of the older corporations, Google is as playful as a puppy.

Google is a friend to Linux and Mac.  Because of the other markets that Microsoft is in, they cannot afford to be nice to Linux or Mac, and the more "features" they have that are incompatible the more people who will be unhappy with a move away from windows.  Enter Silverlight, .Net, ActiveX and all of their other web products.  Try using IE9 on anything but the newest Windows.  And, I'm using Google Chrome on my Ubuntu box to write this post.

Lastly, Google's results are better.  I have a fun example for you all, and I know it's nothing but one example, but it shows what each company thinks of getting relevant search results to the user, and really, at the end of the day, that's what we are all looking for.

I did a straight image search for the word rose, and then added the color filter of green, and here are the results:

Bing has ONE green rose out of fifteen results.  You get better results searching for green rose in the first place and ignoring the color filter.

Google has twelve green roses, two pictures from the movie Green Rose, and ONE rose that is not green.

Like I said, this isn't a rigid test, just one example I stumbled on while working on a lesson plan.

Saturday, January 8, 2011

2D Games with Kitten-Fu, Part Three

Alright, so last time I promised you a second cat and some grass for them to walk on. When I originally got this far in my program I just copied and pasted and created a few if statements in order to take care of the second cat, but instead I'm going to use objects because they are going to be more efficient in this case (where the cats aren't significantly different in how they behave.)
Kitten-Fu is at version alpha 17 now, which is what i will be using for this tutorial. The earlier and later versions should be 100% compatible with what we have done so far.

The Sprites


We have two sprites to create before we work on the next bit of programing. The first is a copy of our first cat with some coloring changes. I also changed the head shape and the way the tail waves-this way they will both have a little different character without needing to re-do all that animation work from earlier.


Next, I'll make a ground sprite. I'm not really happy with the way this turned out. I'm thinking of making a new sprite that is just grass and will be placed higher on the screen along with a second sprite of just dirt at the bottom to give it that street fighter pseudo 3D feel. Remember, I am sticking to 4 colors per 16x16 block to help keep the 8bit retro style. Also remember that transparent counts as a color.


The Code


Let's start with adding the ground tile, since that's pretty simple. First create the ground stamp:

stamp ground("ground.png");
No need to worry about slicing it at this point. When we have more variety then we can convert it, but for now a stamp will work just fine.

Next, let's add a for loop that utilizes the stamp we just created and place it at the beginning of our painting section (after we clear the screen, of course)

  for (int i = 0; i < 8; i++) {
ground.put(i*16, 104);
}

If you compile your program now, it should display the ground tiles across the bottom of the screen.

So far we have just been using structured programing, meaning the code just goes through in order what we told it to do without employing any fancy code. We're going to get a whole lot fancier in just a bit. The next thing we are going to do is add a second cat. We COULD just copy our code and rename all of our variables with a 1 and 2 after them, but what if we need to add a third or fourth cat? (for example if we were making a kitteny RPG) That would get old really fast as we duplicated all of our code four times. So, to solve that we are going to employ classes.

I'm going to move all of the code having to do with the cat logic and painting into a kitten class. Since I am still fairly new to object oriented programing, I don't really feel like I can explain what I'm doing in very high detail, so I'm just going to show you what I ended up with.

If you don't know what a class is, you can think of it as a cookie cutter that you create with its own variables and functions (these have different names when they are a part of a class ... whatever) Once we have the class/cookie cutter set up, we can use it to create instances of our class (the actual cookies). This way, we can tell the program what a cat should look like and then make as many as we need with minimal needless duplication of code.

If you know HTML at all, this has the same function as CSS does, it's f*ing amazing and lets you do all sorts of cool things to control all your similar processes all at once.

Without further ado, let's look at the kitten class code (this goes right after we include KFu on line 5.) Actually, I take that back, I'm going to be converting the code into object orientedness in two passes. This first will be the game logic, the second will be the painting portion which I will cover in more depth than the game logic. okay, for real this time:

int framecount = 0;

class kitten {
public:
int kx;
int ky;
int walkleft;
int walkright;
int facing;
kitten();
void step();
private:
};

I made framecount into a global variable for now and changed the k1x and k1y variables into just kx and ky (make sure they get changed in all the places you were using them!)

Next, let's make the constructor:

kitten::kitten() {
kx = 110;
ky = 88;
walkleft = 0;
walkright = 0;
facing = 0;
}

You'll notice that the above code was basically used to declare and initialize the variables that we're using in this class. Go ahead and delete the duplicate variables at the top of main().

At this point we need to create an instance of our kitten class in main(). I'm going to call it kitten1, but you can name it anything you like. Since we are going to add the paint routine to the class, we will need to call it after we create the screen, so go ahead and add this:

  kitten kitten1;

And now let's make a method (it's basically a function) which will take our actual game logic code that we reference the kitten in and make it available to use with the class:

void kitten::step() {
if (framecount%2 == 0) {
if (walkleft == 1) {
kx = (kx - 1);
if (kx < -16) { kx = 128; }
}
if (walkright == 1) {
kx = (kx + 1);
if (kx > 128) { kx = -16; }
}
}
}

Again, you'll want to delete the code that we have now duplicated and replace it with the following:

  kitten1.step();

Before we're done, take a look at the SDL input handling. We use walkleft, walkright and facing there ... we'll need to point these to our kitten1 instance of the kitten class by adding kitten1. in front of each variable.

Okay! Go ahead and compile your code and make sure it still runs at this point before you continue. If you get an error, read it and take a good look at the line number it gives (if it gives one). Make double sure that you didn't leave anything important out like a semi-colon or a brace. If you still can't get it to compile, take a look at the sample code at the end of this post - we are doing some major revisions to the structure of the code and that can be a little confusing at times.

Once you have your code compiling and running again, let's break it again! we're going to turn the painting routine into another method in our class.

Before we start, we need to change the way we declare our slices and stamps again so that we can separate them into variable declarations and variable values just like we did with the other variables.

  stamp* sprites;
sprites = new stamp("kitten1.png", KFU_LOAD_FLIPH | KFU_LOAD_NORMAL);
slice* stand;
stand = new slice(*sprites, 0, 0, 16, 16);
slice* walk[4];
walk[0] = new slice(*sprites, 16, 0, 16, 16);
walk[1] = new slice(*sprites, 32, 0, 16, 16);
walk[2] = new slice(*sprites, 48, 0, 16, 16);
walk[3] = new slice(*sprites, 32, 0, 16, 16);
I also got rid of the kitt1 from the name of the variables since that won't make a lot of sense when it is part of a generic class.

So, what are those asterisks that we added to our code for? They are memory pointers that we are using to separate the variables. Jeff is possibly changing kfu to make this easier, so I'm not going to try and explain it :-) If you want to know more, read a good introduction to pointers in c++.

Next, we should add the following to the private section of our class:

  stamp* sprites;
slice* stand;
slice* walk[4];

And the following to our constructor:

  sprites = new stamp("kitten1.png", KFU_LOAD_FLIPH | KFU_LOAD_NORMAL);
stand = new slice(*sprites, 0, 0, 16, 16);
walk[0] = new slice(*sprites, 16, 0, 16, 16);
walk[1] = new slice(*sprites, 32, 0, 16, 16);
walk[2] = new slice(*sprites, 48, 0, 16, 16);
walk[3] = new slice(*sprites, 32, 0, 16, 16);

Now, we need to make a method that replaces the painting code:

void kitten::paint() {
if (walkleft == 1) {
walk[anim4]->put(kx, ky);
} else if (walkright == 1) {
walk[anim4]->put(kx, ky, KFU_PUT_FLIPH);
} else {
if (facing == 0) {
stand->put(kx, ky);
} else {
stand->put(kx, ky, KFU_PUT_FLIPH);
}
}
}

Since we use the variable anim4 in our class method, let's make it a global variable next to framerate for now. And then of course delete the original painting code and point to the class method with the following:

  kitten1.paint();

Pretty cool, huh? Make sure your code still runs and debug as necessary.

wooo .. let's take a deep breath and take a look over all the code. Clean up any extra spaces and comment as necessary. Make sure you understand and recognize all of the various parts of the program still.

Now for the fun part, let's add that second kitten!