Programming Class Week 7
2013-Dec-06, Friday 18:42a.k.a.: Lasers, pew pew!
This week and next week are the same project. We're doing an implementation of the old classic asteroids, though our version has sounds and actual sprite-based graphics because the professors programmed a GUI capable of handling such things.
It only took a couple hours to do, though I ran into a problem not based on programming but on math (to the extent that there's a difference anyway). So, you want to move a spaceship in the vacuum of space. That makes you need to take Newtonian mechanics into account, unless you're making X-Wing and want World War II dogfights in space, but we aren't. Except for the friction. We have friction in space. It's in the design requirements for the program.
I guess this like how in Power Rangers the moon has an atmosphere.
Anyway, Newtonian mechanics. If you don't know what I mean, it means that if you go forward, and then go left, you maintain your forward inertia and end up traveling at an angle, so I needed to calculate properly to make sure that happens when you're moving the ship around. In summary, the movement keys control acceleration, not velocity (at least for forward movement). Fortunately, it turns out that it's possible to turn an angle into a movement vector as long as you have the angle in radians, using the cosine and the sine of the angle. The problem I ran into was in correctly adding that to current movement to produce the new movement and make it look smooth, which took an hour and turned out to be incredibly simple, much like my problem with brackets and list comprehensions earlier. Just...add them. And include a constant to make sure the movement is smooth and scales up to the maximum possible velocity slowly, but that's easy enough. I'm starting to wonder how much of programming time is wasted in making simple problems harder than they should be. I guess that's why the Ballmer Peak is a real thing.
This is why I described programming as "math with more words" on Facebook. Even though the programs do the actual calculations for you, you still need to understand enough math to write the equations correctly. Or enough to Google how to write the equations correctly. Ahem.
Also, I wrote this method for the Ship class that handles the behavior of the player's ship:
On the topic of things I learned this week, I learned about Magic Numbers, which are when you find random inexplicable numbers in the code whose value seems to be pulled out of nowhere. I did that when I wrote Pong and got called out for it, and almost did that this week when I was trying to make sure flying off one side of the screen would put the ship back on the other side. I was all ready to write in the raw numbers of the size of the playing field when I realized that the program template had set the Width and Height as globals precisely so that I could just say, for example, “pos[0] %= WIDTH” and then if I ever changed the size of the playing field, the rest of the code takes that into account and I don’t have the ship randomly disappearing and reappearing in other places.
Next week--the last week of the course--we deal with actually making the asteroids collide with the ship, making laz0rs blow up the asteroids, spawning new asteroids, keeping score, and so on. And then we're done! Though at the moment, my current plan is to keep tinkering with it. Adding some kind of limited-quality teleport, maybe adding powerups, other ships that try to kill you, that kind of thing. Sure, it's derivative, but it'll be a good learning experience.
This week and next week are the same project. We're doing an implementation of the old classic asteroids, though our version has sounds and actual sprite-based graphics because the professors programmed a GUI capable of handling such things.
It only took a couple hours to do, though I ran into a problem not based on programming but on math (to the extent that there's a difference anyway). So, you want to move a spaceship in the vacuum of space. That makes you need to take Newtonian mechanics into account, unless you're making X-Wing and want World War II dogfights in space, but we aren't. Except for the friction. We have friction in space. It's in the design requirements for the program.
I guess this like how in Power Rangers the moon has an atmosphere.
Anyway, Newtonian mechanics. If you don't know what I mean, it means that if you go forward, and then go left, you maintain your forward inertia and end up traveling at an angle, so I needed to calculate properly to make sure that happens when you're moving the ship around. In summary, the movement keys control acceleration, not velocity (at least for forward movement). Fortunately, it turns out that it's possible to turn an angle into a movement vector as long as you have the angle in radians, using the cosine and the sine of the angle. The problem I ran into was in correctly adding that to current movement to produce the new movement and make it look smooth, which took an hour and turned out to be incredibly simple, much like my problem with brackets and list comprehensions earlier. Just...add them. And include a constant to make sure the movement is smooth and scales up to the maximum possible velocity slowly, but that's easy enough. I'm starting to wonder how much of programming time is wasted in making simple problems harder than they should be. I guess that's why the Ballmer Peak is a real thing.
This is why I described programming as "math with more words" on Facebook. Even though the programs do the actual calculations for you, you still need to understand enough math to write the equations correctly. Or enough to Google how to write the equations correctly. Ahem.
Also, I wrote this method for the Ship class that handles the behavior of the player's ship:
def chargin_mah_lazor(self, pew_pew_pew):
global a_missile
lazor_bank = [self.pos[0] + angle_to_vector(self.angle)[0] * self.image_size[0] / 2, self.pos[1] + angle_to_vector(self.angle)[1] * self.image_size[1] / 2]
if pew_pew_pew == True:
a_missile = Sprite(lazor_bank, [self.vel[0] + angle_to_vector(self.angle)[0] * 3,
self.vel[1] + angle_to_vector(self.angle)[1] * 3],
self.angle, 0, missile_image, missile_info, missile_sound)
We can always use more laz0rs in our games, right? The documentation calls them missiles, but it's not like they have missile graphics. They're little blue star-shaped energy balls. That's as close to an 8/16-bit laser as makes no difference.On the topic of things I learned this week, I learned about Magic Numbers, which are when you find random inexplicable numbers in the code whose value seems to be pulled out of nowhere. I did that when I wrote Pong and got called out for it, and almost did that this week when I was trying to make sure flying off one side of the screen would put the ship back on the other side. I was all ready to write in the raw numbers of the size of the playing field when I realized that the program template had set the Width and Height as globals precisely so that I could just say, for example, “pos[0] %= WIDTH” and then if I ever changed the size of the playing field, the rest of the code takes that into account and I don’t have the ship randomly disappearing and reappearing in other places.
Next week--the last week of the course--we deal with actually making the asteroids collide with the ship, making laz0rs blow up the asteroids, spawning new asteroids, keeping score, and so on. And then we're done! Though at the moment, my current plan is to keep tinkering with it. Adding some kind of limited-quality teleport, maybe adding powerups, other ships that try to kill you, that kind of thing. Sure, it's derivative, but it'll be a good learning experience.