Monday, April 25, 2011

A House of Cards

The title of the day was almost something about a fax and then I realized that almost nobody uses a fax machine. Further anybody that reads the development diary of an indie game probably thinks that a fax machine falls into the same category as a wax tablet or something made out of papyrus. So that went right out the damn window as far as a title was concerned.
Which is kind of shame really, because the analogy really held up with today's bit of coding. Getting back to the cleanup of the C# code, I got to putting the Fortress (and by extension, anything that acts like a Fortress Enemy, like Turrets and Rocket Launchers) together correctly. The first enemy that I did was the Fighter Plane. The thing is that a Fighter only shoots in a single direction. So when I had the Fighter Enemy phone back to the mothership and ask for a bullet, there was only 1 direction that said bullet would go in.
Everything the feck else though, has a menu of options with 360 things on it. So sending the request (which is just a single number - cause I like those) suddenly had to include a lot more information in it. So I thought that I would send a code up through the request, a short series of digits that would represent different aspects of the speed and direction of the requested bullet. So the code uses the 1000's place for the X value, the 100's place for the Y. So a value of 3200 would be 3 to the right and 2 down.
It didn't take me long to realize that there was almost no way to transmit negative numbers this way, which is kind of problem because anything that goes to the left or up requires that one of the values must be negative (the value 0,0 is the upper left hand corner after all). So fix that I added markers in the 10's and 1's place to represent the negativity (so negative!) of the numbers. So 3201 was 3 to the right and 2 up.
This of course fell down hard because I was adding bad values. I wasn't changing them into their absolute values, so adding -100 and 300, just got me 200, which is just wrong in so many bloody ways.
After fixing that, the turret would shoot in the opposite direction of the player, but at least now it was doing so consistently. So a tweaked some functions and...broken. Tweaked some more and found the same issue. Make a couple minor adjustments and then...still shithoused.
Eventually, I added a "-" to the front of the directions and it just worked somehow. Which brings me to the titles. You see, it works now. It's completely portable. I have no exact idea which of the things that I did fixed it, or which of them I'll break it with if I decide to dick with it. Thankfully, it works so I won't have to touch it. I can just enjoy it and the effort that went into it, like, well, see the title.

Saturday, April 23, 2011

Phone Home

I've spent the last couple of days playing the role of digital marriage counselor, doing my best to get the different parts of the Paper Zeppelin code to sit down and chat. The issue is that the specific objects that I want to talk about, don't really exist in the code.
I'll explain. On a basic level, the Paper Engine only creates things. It works almost like a really advanced version of the code I put in The Thief's Tale that dealt with background objects. So I tell the system to make an object, and then every time the game cycle runs it updates all of the objects. I get the impression this is how most proper game engines work. The silly thing is that the objects that I create they never really exist in any meaningful way. In Thief there were a shitload of rectangles, but each of them were distinct. I could explicitly reference any one of them if I needed to because they were numbered 1-12. Now in Paper Zeppelin if I make ground it's a spawned thing. It isn't numbered in any way. The only real way that I have to have them interact is to put them into an explicit list that I can reference. So when I need to see if ground is touching I ask the computer to check against everything in the Ground List, but if I wanted to know about the specific piece of ground at 300,100 - well that's too bad.
This predicament led me to a kind of cool function that is part of the C# library called Static. What it does is it make a function considered to be an integral part of an entire class. So say I had a function for the players that checks their controls or something, if I make that Static I can call that function from anywhere. The problem that I discovered was that the function that was called was part of the Code, but not an integral part of the object that was running that code. So if I made a static function that wanted to call a value, the system would crash because there is no value because I was not referencing a specific Fighter Plane, but only the Fighter Plane Code as a whole, which seems pretty ridiculous.
What I was trying to do was make the Fighter enemy shoot a bullet. So the next idea was to fetch the player list, so it would know where the player was and do its thing. So I tried to have it look at the list of all the players by making the player list a Static (or integral) part of where it lived. After doing this I discovered a weird thing - the player list did not want to be Static. It created all kinds of problems wherein I couldn't call my own code. The answer for this came from the structure of the code itself.
This takes some explanation, so bear with me. In the Paper Engine there is the Main game code. This code creates an instance of a Class called Sprite. The Sprite Class in turn creates a code Class called Sprite Manager. The rest of the stuff, everything from players to enemies to explosions are all hanging off of the Sprite Class and the SpriteManager Class. The Sprite Class is the "Arch" Class that more or less lords over all the other Classes (which are enemies and anything else that would be drawn on the screen). It defines what they are, what they need to run and handles all of the drawing and other super basic stuff so that the SubClasses don't have to worry about it. The Sprite Manager is responsible for creating new versions (or instances) of the SubClasses and making sure that they update and brush their teeth.
The thing about being able to look at stuff is that you can only look at things that are below the part of the code that wants them. So the Sprite Manager can get almost anything from any of the SubClasses. For example, it can know what position stuff is in and uses this information to calculate collision. On the other hand, the Fighter Planes cannot get information from the Sprite Manager, since it is "above" them. Further, it can't call on information that is next to itself, like the Fighter Plane cannot find information about a player directly.
Going back to the original issue, the list of players could not be considered static, or an integral part of the Sprite Manager Class. The problem was that list itself was part of a larger Game Component Class that lived inside the Arch Sprite Class. Since I can't call upstream, that didn't work. That also made it impossible to call the SpawnBullet() function from inside the Fighter Plane code. It lived somewhere else. Even worse, since SpawnBullet() even mentioned something in it that was "above" where I was calling, the whole thing fell down. It's like the system can follow the specific information and know where it was originally from.
Long story short was that I could have the Fighter Planes know where a player was (since that information could be accessed by the Sprite Manager, which in turn could feed it downstream again to the Fighter Planes), but couldn't shoot. The solution is our titles, which I've finally gotten to. You see, the Fighter Planes just had to ask permission. I was trying to make them do everything themselves, when instead it was far easier to simply just ask. Like this:
"Hey Fighter Planes, do you want to shoot a bullet?"
"Yep, we sure do."
"Alright, let's do it then."
"Eehhh, I can't. It won't let me."
"So?"
"I want to do it all by myself."
"Why isn't there a bullet then?"
"Mean old Sprite Manager won't let me push the button."
"Why don't you ask then?"
"Okay, Mr. Sprite Manager, can you push the button?"
"OKAY."

How I did that was add a new function to the Sprite Arch Class. Now it has a thing called Summon(). It does one thing - pass a variable back from the SubClasses. That's it. However, when the Sprite Manager gets that, it does different things based on what that number is, like create a bullet. I did have to add that to all of the SubClasses, but now that it works, it's pretty awesome.

- Whew. That was a lot of explanation into how the basic Paper Engine is designed. Sorry about all of that. The question then is, why the hell would I explain how that works, and why care? The reasoning is this - I've made the engine generic.
The thinking goes that all the engine does, is spawn things with certain behaviors, track their interactions, handle controls and drawing. Really any game engine does these things. What makes a game specific is the kinds of things that are created. Say I create a ball, and players and bases, I could make a baseball game. Say instead I make a soldier, and some guns and some cover and I could make a cover based shooter. The engine underneath is 95% the same in both cases. Some of the way rules are handled is different, but most of the gameplay is really the objects that are in the game.
So, moving forward from here to anywhere, the Paper Engine can handle almost anything that I can create with it. I'm making Paper Zeppelin, but it will also be able to power The Star Frog EP, and even Silver Knight. Shit, I could rebuild The Thief's Tale with it. I can build whatever from here moving forward using my dedicated engine. Having it already work will allow me to do crazy fast iteration in future projects and hit the ground making the objects that will define the game itself, not worrying about drawing stuff on the screen and frame rates. A custom engine that I can do anything with. Best thing ever.

I've got a golden ticket...

Sunday, April 17, 2011

Three Sixty and No More

Okie dokie then.

Wait, no, let's think of something less lame than "Okie dokie" to start on of these things. Almost anything really will work. Let's try this instead.

So I got more thing to work today. On tap for today was getting the Bomb type finished off. I ran into a kind of weird problem along the way. Every time I would fire, the bomb would stop working. For the life of me I couldn't figure it out. Turns out that I was doing the math wrong. Having a bomb in the system is tracked in a weird way. Since I only have a single misc field, and it happens to also control the firing timing for players, I would up instead using some simple division and using the 1000's place instead. I can do this because C# has a cute was to do Modulo Division. I may have explained this before, but long story short is that it divides a number and gives you the remainder. This allows me to do different things based on where a digit happens to appear in it's own line.
The trick is though that I was resetting the player's machine gun incorrectly. So every time I shot it changed the Misc value back to the default "I just done getting shootin'" mode and it promptly forgot that it ever had a bomb. It was pretty dumb, but now it works.
In the back end of the system here's what is happening. The game will load up an icon for with a bomb on it. Eventually this will be something else, but for now it works. When a player hits it, it disappears, adds a new bomb object that is set to follow the player around. Then when the player hits the trigger on their controller, it erases the bomb following them around and creates a Bomb Crasher type that falls and makes with the killing. It's awesome because it works.
Also, after having some play testing done, it was found that shooting in just the 8 cardinal seemed off. She would mash the stick in a direction and the bullets would round themselves off, making it seem as if it was fighting her to shoot correctly. Originally I thought this was a good idea. Since I couldn't (at the time) make true 360 degree shooting happen it also seemed okay. Now though, I co-opted that sweet trig code from the other things that are able to shoot in all directions and, blamo, now the players can too.

I began to realize something while coding stuff up today. I have come to the conclusion that I am using large parts of the C# language incorrectly. The true power of the language lies in the robot code that all of the different objects that I create can follow. Each of them having all of their own code self contained within, making the other bits of code, the structural bits, more easy to use and understand.
Instead I've managed to build myself another monolith of code like I was still using Blitz Basic. Oh, yeah, it works. The modular functions that I write pretty much guarantee that to some extent, but it's not working cleanly. To wit, I have a function that handles all of the Fighter Plane Enemy AI. As far as it knows, the Update Robot code for the Fighter Planes doesn't even exist. Instead, right before I update all of the enemies, I pull a little "if" statement that checks what kind of enemy it is and runs the AI function that I wrote. Does it work? Of course it does. Is it in the right place though? Well, not really. I should live inside the Fighter Plane Robot Code inside the class. Not in the main chunk of code that draws and checks collision and things. Basically, the structure is a little crap and I don't think I'm happy with it.
So, as I continue I'm going to start to modify the code as I fiddle with it. Further new things that I create are going to be done correctly from a structure standpoint.
The issue then becomes, or rather has always been, how the fuck do I make things talk to each other? You see, when things live in different parts of the code, that section more or less owns them. So trying to get, say a Player's Position from inside the robot code is almost impossible. Usually it's because I don't have permission. To access my own bloody code.

I foresee a lot of swearing.

Saturday, April 16, 2011

Carta Mundi

Oh yeah. Hells to the yeah. Yep, I know that last thing bordered quite precariously to being "douchey" but I honestly don't care. The Map works. The import function into Paper Zeppelin works. I can build (and have!) an entire Paper Zeppelin level using Open Office. It's pretty damn awesome, and was the trickiest bit of programming I had thought there was left to do, and now it's behind me like so many vanquished foes and lusty women (not really).
It turned out there was a magic word. It wasn't "Sesame" and it wasn't "Rapunzel let down your golden hair." Nope, it was File.ReadAllLines. What it does, or at least seems to do, is read a file that I feed it. It reads all the lines and if you do something like this:
String LevelData[] = File.ReadAllLines(theLevel.csv)
It makes the Level Data whatever the hell is in the file. Since the whole engine was already set up to assume that everything was read out of that LevelData information, changing where and, more importantly, how the information got there once I set it up correctly, it just ran. So cool. So bloody cool.
Couple thing popped up. First of all, I had to set up an Importer. C# and specifically Visual Studio (the program or "Integrated Development Environment" ie "IDE" that let's me code) has a lot of options for importing information. That's because there is a lot of different types of information that goes into a program and a video game in particular. It may need to import pictures, data, sound effects, 3D models, textures (the pictures that wrap around 3D models to make them look good), music and all kinds of other stuff. Picking the wrong kind will make the system crash because a picture and a sound effect have fundamental differences in the way that the computer reads and understands their information.
The thing is, there wasn't an Import option that said CSV file. So I did a few and crashed the program a couple of times until I ran across an option that just said "XML Content." It still crashed, but the other options made even less sense. It turns out that C# and Visual Studio will also want to preprocess information and assets. What that means is instead of going to look for the file and then reading it, C# wants to do all of that crap before the program starts to run. Then it can optimize it and make it run fast. Again though, there are a number of different options. The thing is, I really didn't want the computer to do anything to my level files. That seemed stupid. I just wanted the pure text and the sweet characters that live there, so I selected "Don't Preprocess my Stuff Jerk."
Then I hit F5, the magical key that unleashes Paper Zeppelin at me. It worked...sort of.
First, a quick explanation. This "CSV" file that I keep mentioning is called that because CSV stands for "Comma Separated Value." The files are then named like this : Stuff.csv.
If one were to open a CSV file in a spreadsheet program like Excel it would have values in the different cells like a normal spreadsheet file would. However, if you opened it in something like Wordpad it would look something like this:
A,B,C,D,E,F
When Excel reads that it would put all of the different letters in their own cell. The other thing is this - the letters aren't saved like that by default. No, because that would be easy. Instead, because they are Characters, they are saved like this:
"A","B","C","D","E","F"
But it gets stupider. They have the little quotes only because they are characters (or words, words {or as they are called in programming "strings"} also have quotes). Other things, like say a period, don't get that special treatment.
The reason that this was a problem is that the whole thing was read into the system and it assumed that all the commas and quotes were there on purpose. When I made a quick map that loaded ground, it had blank spots all over the place and nothing lined up, because when I asked, "What's the next character?" the computer replied correctly with, "It's a quote thing...so I ignore it."
Anyhow, I had considered coding a way to remove the quotes and the commas, but then instead I wondered if I could change Open Office to do it for me. Which it turns out it can. So I turned off the quotes and the commas and the thing just worked. So, hurray for that.

-For those of you playing along at home, the biggest reason that I am so surprised by all of this is that you may remember that I built a custom level editor for The Thief's Tale. It took me almost 2 months. I got this sexiness done in an afternoon. What I am now going to do is set up a template for making the levels. I can make colors and stuff appear around different values. That's awesome! I haven't been this excited about a spreadsheet program since, well, never. Spreadsheet programs really aren't known for being excitement inducing.

Monday, April 11, 2011

...and Boom Goes the Dynamite

Rockets works now. First though let's back things up just a moment and let's review a conversation that I recently had with my computer.
"Alright computer, I have explosions and rockets. Everything looks okay jah?"
"Yep."
"Cool. So let's run this thing and...where are the rockets?"
"I made them. Didn't you see them?"
"Nope."
"Look harder."
"Fine you rotten thing. I made the rocket exist for a really long time. Now I can see them. Where are the explosions?"
"I made those too. I think you are going blind."
"Dammit, no. I would see a bloody explosion."
"You'd think so wouldn't ya?"
"Okay. Let's do this. Let's make an explosion every time the rocket is updated."
"Are you sure?"
"Yes, I'm sure. Do it you bastard...you crashed."
"Too many explosions."

Eventually the conversation boiled down to this:
"Okie dokie then. You run the code on line 50 and line 52. But line 51 you skipped. Why is that?"
"Line 51 is hard."
"Eh?"
"On line 51 I'm supposed to make an explosion, and I don't want to."
"Well why the feck not?"
"Cause explosions are hard. I don't wanna."
"Please?"
"When does Spongebob come on? I love that show."

Turns out that the computer (that stupid, hateful, wonderful thing) was doing everything I told it to do, but it was happening all so fast that it didn't ever draw any of it. Which leads me to the odd conclusion that everything on the screen isn't drawn every cycle like I thought it was. Odds are the C# is using some kind of internal clock to keep track of when to draw things. This is different than my Blitz Basic solution that checked to see how long it had been since the last time to decide to update again. I'll have to keep that in mind.
Right, so now explosions and the rockets that bear them into the world work. It's pretty awesome really. Bullets and rockets and explosions and planes and a zeppelin. For the first time today I played through the test level I built, dodging bullets and rockets and shooting and I found myself having a pleasant time. The fundamentals of play are at least fun in Paper Zeppelin.
A couple of things come up though. First of all, I think that I want wreckage. When I shoot down anything it turns into a ball of flame and falls to the ground. When it hits it simply disappears. Considering that I shot whatever it was, watched it fall, watched it hit other things and then hit the ground, there seems to be a lack of coherence in the experience. My brain expects there to be something left over. Preferably something that also has flames on it and smokes like a nicotine addled chimney. Hypothetically, I could create a single Class of broken things and give them different pictures when I create them.
Going back to my Chicken example from way back, I can give the Chicken any kind of variables. I can make tall ones or short ones and red ones or yellow ones. Heck, I can even combine the variables and make short red chickens. The point is that no matter what the variables are, the basic code that makes my robot chickens run is the same. They all follow the same rules.
So, with a crashed enemy, all I need to do is hand the wreck a different picture.
"What's that? A Fighter just crashed? Okay then, make a Wreck and have it hold this picture of a crashed Fighter Plane. Great!"
It's more or less how Crashing enemies work. I make a crasher and based on the type of enemy I give it different variables.

In any event, next up is creating the Rocket Launcher. I'm thinking that there should be some way for the Rocket Launcher to let a player know that it is planning to shoot. I could just create an animation that lines up exactly with the firing sequence, although that would make a damn big picture. The other alternative would be to use the misc field to somehow update the frame being drawn. Then I could slow down the animation to match. This would be preferable, but like what I found out before, the drawing happens when C# thinks that it should. So I very well may run into something stupid along the way.

Thursday, April 7, 2011

Rocket Man

Turrets are done now. Do they work perfectly? Not quite. But here's the thing and here's why they are now emblazoned orange on the done list, they're working. Also, it occurred to me that the sprites that I have aren't going to be the sprites that Paper Zeppelin will ship with, so there's not a lot of reason to get all fiddly with it. The Turrets turn and they fire and it looks like it's working. Any of the little things that look like deuce won't be relevant when the new art gets plugged in. Hence, they're done, especially from a coding standpoint anyway.
It looks like we are rapidly reaching a point where I will be out of necessary things to code. I mean in terms of the major players in the game that need their own classes I'm making pretty good time. Let's see. As of this writing I have the stuff pertaining to the bomb, the bases and the Rockets. I'm saving the bomb part for last, since it has to do with things the player is doing. So I'm right in the middle of making rockets happen.
Tonight (Live!) I got the rockets installed and they work more or less. I mean, they shoot, and they have an animation that I totally stole, and I managed to create a cute adjustment to the code so that the turrets that I've rigged up to shoot them also pass along the rotation that they worked so hard to figure out. So rockets fly out in all manner of direction and look pretty sweet. They still move way to damn fast, but I have something to work with.
Speaking of rockets, the Design Document says that they are supposed to work by exploding after a set time. It also says that they do an average of the player positions and make that the target. Let's consider for a moment these assumptions. The exploding thing works, and I kind of like it on a certain level. It is also appropriate for shooting at Zeppelins but it's called "flak." What I do have to install though, is a way for players to know when the damn thing is going to pop. Right now the prevailing theory is making the fire / smoke trail a different color right before shiny happens.
The second assumption lies in the targeting system. I could just pick a random spot on the screen and shoot it, but that reeks of sadness (not unlike an AFI concert...I assume). If we go by the average, then we have a slightly different problem. It has everything to do with sample size. Before you get worried, I'm not about to drop the mathematics like it's hot. Let's say we have 4 people and they are all over the screen. There's lots of different options to add together for an average and the rocket will shoot more or less into the center of them. Now, assume that there is only 1 person. The "average" position will just be that players "actual" position and the rocket be aimed directly. With that in mind I don't think that rockets will be too prevalent in any of the single player maps.
Another thing in the document is that the rocket firing brutes can't be damaged. I no longer think I like this. The original thinking was that rockets are too slow and sad to be any real threat. Instead they are a minor annoyance. Having most of the game available to play with shows me that Paper Zeppelin is surprisingly fast and hectic. It plays a little like AeroFighters, only with duel stick shooting. So there are an imperial (as opposed to metric [oh snap! measurement scale burn!]) shit ton of bullets on screen at any given moment. Add 4 players doing that and the chaos gets pretty, well, awesome. In this kind of environment a slow moving, annoying and effectively indestructable enemy doesn't really cut it. So I think I'm going to show them another way to die...involving bullet bills...in a very uncomfortable place.

While writing all of that I had a Bomb idea. Not a "Bomb" as in "da Bomb" idea, but an idea pertinent to bombs in general, and the Bomb item in particular. I'm thinking that the Zeppelin sprite always has a bomb. The thing is that I don't show the whole sprite, only the top half with just the zeppelin in it. Instead, when the bomb gets picked up, I can change the display and player parameters.
Although, thinking some more about it, it would change the color of the bomb depending on who is carrying it. No, I'll do it the hard way so it looks right.

Earth below us, drifting...falling...

Wednesday, April 6, 2011

300

Wowsa. It's taken several years, but this is the 300th post. I've taken to reading some of the old posts, including the one marked 200 from almost 2 years ago. The Lost Weekend seemed to just devour time and the posts with it. The project is different than the last post, and me along with it I think. I've come to the conclusion that, if nothing else happens, if my long awaited Exodus never materializes, I'm content doing this, right here, for as long as I can manage to open a laptop and create magic.
It's a kind of odd epiphany, especially made now. One may wonder when the original whole point of this was to move on, why the change of heart? The answer is not so simple yet incredibly so. I find this, after 300 posts and the days weeks and months worth of work that I've invested, to be a wonder in and of itself. My projects, the whole Star Frog Games Studio, at some point has become less of a means to an end, and more of a means unto itself. I don't work on these things because I'm hoping that they go somewhere, I do them because I have discovered the very act of working on them makes me happy. If this happens to lead to my Exodus (which seems more and more likely the longer I do this ironically yet appropriately) then so much the better.
So, here's to a dozen projects and a dozen more that will proudly have Star Frog Games labeled at the front. Here's to writing post 400 and 1000 after that.

- I almost called this post SohCahToa, an old Indian maiden that is also a mnemonic device for remembering which angles go with what sides when handling a triangle. Instead Blogger told me that this was post 300, so I went with that instead (a tradition worth keeping, although I almost instead went with "Spartan"). In case you're wondering (more math incoming, so look out!) SohCahToa stands for Sine = Opposite / Hypotenuse, Cosine = Adjacent / Hypotenuse, Tangent = Opposite / Adjacent. The second part is the sides of the angle. I'll spare the details regarding noticing them, and just move on.
Although that doesn't have much to do with why I would have selected that specific title. Instead I got the Turrets to turn and work more or less. The problem with the little bastards was this equation : C^2 = A^2 + B^2
Yep, I totally forgot the squared business for the C, which caused the math to go all bonkers. Let's see why. Say A is 3 and B is 4, then we can calculate that C should be around 25 since it didn't do the square root part of the equation. When we then do the Sine math on it, it comes out to be a fraction of a Radian since it rotates all the way around and comes back around again.
So what does that mean? Well, it means that even though you move quite a bit, the turret will only rotate just a wee bit, which looks like it's shivering from the cold.
So that got killed hard. Now they aim like they are supposed to. Little beasts.

-Along the way I also made a small modification to their aiming code. I thought that it was stupid that they could shoot below themselves. If you think about a turret, they usually don't need to aim down. This is even more true for turrets designed to hit air targets. So now before they shoot they double check to ensure that the player they would like to shoot at is at least level with them. It works, and I like it from a design perspective.
The thing is, most of the design wants to push the player towards playing a specific way. Specifically, it's the fact that things fall down after they get shot. Being below anything you are shooting becomes a terrible idea. The game is kind of built around that conceit. Consequently, whenever I can do things to force a player to explicitly not do that are good things. If being high is always a good idea it encourages the player to always be above regardless of the circumstances. Adding mechanics and play items that would prefer the player be below things, such as the new Turret code and the way the player can't shoot downwards while carrying a bomb, force a player to always be evaluating the specifics of the game and change how they play accordingly. Add into that the ability to have up to 4 players simultaneously and the gameplay opens itself up quite a bit. As a designer, I like that.
I've talked at length about control as a designer, that having a tight grip on the control is how I can build fun. Sometimes though, especially when it comes to a game like Paper Zeppelin, the fun will come from a player figuring out how to do it on their own terms. At which point all I can do is offer up the toys for them to play with. Then it's my job to design some damn cool toys.

-Speaking of toys I have decided that I need a turret that is upside down. I probably also need a Rocket Launcher that is upside down. This way I can put them on the ceiling, which would allow me to do some cool shite with the level designs. This came about after I put the code in that made the Turrets only shoot above them. It creates an odd disconnect since, logically, there can also exist Turrets that cannot shoot above themselves and only below. Normally, this would be an issue (see the last section of rant) but since inverted Turrets would be attached to ground, the player couldn't be "above" them in any meaningful way. So that's next on the hit parade. I'll get that done and move along to the Rockets. That should be interesting.

Sine Sine Cosine Sine, 3 point 14159...

Monday, April 4, 2011

Fun with Turrets

If you'd look over yonder ==> at the Big List for Paper Zeppelin, you'll notice that the Turrets aren't all orange yet, mostly because they aren't done. Oh they work all right. They shoot bullets at the player just like the Flying Fortress type enemies do and they are hard-ish to kill on account of their ground based orientation. So one may be tempted to consider the thing all done and just go ahead and add a plash of color. I am not one of those, um, ones.
Instead I'm driving myself to distraction because I can't quite yet figure out the math involved to make the turret aim. Visualize for a moment a cannon firing. The most basic of things that it does (other than the loudness and the explosion) is be pointed at something. A cannon isn't just pointed at something and then the ball goes wherever the heck it thinks looks nice this time of year. The direction the cannon is pointed has specific implications on the resulting trajectory of said flaming ball.
But now, the Turrets in PZ do not do that. At best I've gotten them to point in vaguely the direction, but it still looks awful. From a design standpoint it would be nice to have a visual way to let the player know where a shot may be coming from. Granted most shooters of this type usually forgo the whole thing. Consider a game like 1943, the big plane enemy bosses just have guns and bullets spray out. There is no visual and it works out okay. The difference is that PZ is designed from the get go as multiplayer. The distinction is where an enemy is shooting is important to hopefully help make sense of the chaos. Similarly the Fighter Enemies will probably spawn in different colors so the players can know who they are after.
The problem with all of this comes from a coding standpoint. Going back to the post a while ago involving trigonometry, I know that when a bullet fires it has a certain, measurable, change in its X and its Y. This in turn is used to calculate the trajectory of the bullet. The odd thing is that the rotate function of C# uses something called a Radian. Mathematically speaking (oh no, here we go again) a Radian is the amount of distance along the outside of a circle equal to the Radius of that circle.
I'll explain. Let's say we are on a floating ball in space. We know that the whole ball is exactly 20 steps across. So if we drew a circle on the ground (of a different surface) that is the same size as the ball we could walk across in 20 steps. So, if we all remember 7th grade math again, that means that the Radius, or distance to the center is 10 steps.
If we go back to the ball in space again, a Radian would be if we walked 10 steps along the surface of the ball. Since the Circumference is 2RTT squared, we know that it takes 2TT Radians or 2 * 3.14 * 10 steps to walk all the way around our space ball.
So yeah, it's kind of a funny way to measure. Especially so after all the Astronomy lessons involving angles and arc minutes and seconds.
But I digress. I suppose that since I know the distances it's really just another way to draw a triangle. So I could use the Sine of the Triangle and...oh noes, more explanation incoming.
Assuming that we have all forgotten what I am talking about, a right triangle has specific names for the different sides and the angles that live inside of them. We're dealing only with right triangles (the kind with a 90 degree corner) because everything in the game is measured in X and Y, and the changes in those numbers. It can be graphed pretty well coincidentally. Anyway, the Sine is the internal angle of the triangle that is next to the long side. Since we were dealing with bullets, that would be the side of the triangle that the bullet would travel along. I can calculate that angle with this bit of math :

sin A = Opposite / Hypotenuse

Or to convert that into something that looks like it belongs in Paper Zeppelin

Shot Angle = Y Trajectory / Shot Length

So let's plug in some numbers now. Say the shot is 3 high and the length is 4.

Shot Angle = 3/4 = 13 degrees or .68 Radians.

Thankfully, after all of that it turns out that C# does all of its angle math using Radians, so I probably don't ever have a convert a damn thing, which would be nice.

- Now then, how do we apply of this back to the bloody titles? I'm thinking that maybe the turret that is tracking a player will always do that angle math. Currently the system only does those calculations when it's thinking that it may want to shoot. If I did the math that calculates the shot trajectory I can use the results to find the angle that the Turret should be pointed in. I then just change the rotation value of the turret to match. I feel an experiment coming on.

..and the results are in. The math works, but the code isn't being nearly so cooperative. For some reason the Turrets just sort of wiggle a little when you get close. It's like they're all excited or something, or maybe cold. I like to think that they're thinking, "Oh, oh I'm gonna get to shoot now. Here it goes! BOOMIES!" Of course I know better, but I now I can think I've given the little bastards personality while I try to figure this out.

-I've noticed a distinct increase in the amount of math involved with Paper Zeppelin, especially compared with The Thief's Tale. I've come to realize that the gameplay of a shooter involved way more geometry than the pretty quick and loose gameplay of a platformer. I mean if the math is just a little off in a platform game it's not all too bad. Things in it seem to be more about calculating certain numbers after a certain time, like the arc of a jump. These things of course work just as well when the math is wrong. It's not like the whole thing falls apart or sucks. You can tweak the numbers until it fits. On the other hand a shooter is almost entirely math and geometry. If the math isn't working there, then the game is just broken and stupid. I think that I'm past the part where I get to constantly explain mathematics. The stuff left on the List seems pretty basic, but then I'm sure I'll surprise myself.