Python 006 - An Asteroid?
I’m at a low energy point but maybe I can get an asteroid up.
First, I’ll fetch the points from one of the Kotlin versions.
private val rocks = listOf(
listOf(
Point(4.0, 2.0), Point(3.0, 0.0), Point(4.0, -2.0),
Point(1.0, -4.0), Point(-2.0, -4.0), Point(-4.0, -2.0),
Point(-4.0, 2.0), Point(-2.0, 4.0), Point(0.0, 2.0),
Point(2.0, 4.0), Point(4.0, 2.0),
),
listOf(
Point(2.0, 1.0), Point(4.0, 2.0), Point(2.0, 4.0),
Point(0.0, 3.0), Point(-2.0, 4.0), Point(-4.0, 2.0),
Point(-3.0, 0.0), Point(-4.0, -2.0), Point(-2.0, -4.0),
Point(-1.0, -3.0), Point(2.0, -4.0), Point(4.0, -1.0),
Point(2.0, 1.0)
),
listOf(
Point(-2.0, 0.0), Point(-4.0, -1.0), Point(-2.0, -4.0),
Point(0.0, -1.0), Point(0.0, -4.0), Point(2.0, -4.0),
Point(4.0, -1.0), Point(4.0, 1.0), Point(2.0, 4.0),
Point(-1.0, 4.0), Point(-4.0, 1.0), Point(-2.0, 0.0)
),
listOf(
Point(1.0, 0.0), Point(4.0, 1.0), Point(4.0, 2.0),
Point(1.0, 4.0), Point(-2.0, 4.0), Point(-1.0, 2.0),
Point(-4.0, 2.0), Point(-4.0, -1.0), Point(-2.0, -4.0),
Point(1.0, -3.0), Point(2.0, -4.0), Point(4.0, -2.0),
Point(1.0, 0.0)
)
)
We’ll want to massage those into a more Pythonesque form, like the ship ones:
raw_ship = [vector2(-3.0, -2.0), vector2(-3.0, 2.0), vector2(-5.0, 4.0),
vector2(7.0, 0.0), vector2(-5.0, -4.0), vector2(-3.0, -2.0)]
And we will have to expand them but I think we can use the same approach as in the ship. I’ll just mash them in Sublime until they submit.
After just a bit of hackery, I have this:
class Asteroid:
def __init__(self):
self.position = vector2(u.SCREEN_SIZE/2, u.SCREEN_SIZE/2)
self.surface = self.prepare_surface()
def adjust(self, point):
center_adjustment = vector2(32, 32)
return point * 4 + center_adjustment
def prepare_surface(self):
surface = pygame.Surface((64, 64))
surface.set_colorkey((0, 0, 0))
adjusted = list(map(self.adjust, raw_rocks[0]))
pygame.draw.lines(surface, "white", False, adjusted, 3)
return surface
def draw(self, screen):
half = vector2((32,32))
screen.blit(self.surface, self.position - half)
That includes an adjustment size of 4, and there’s no way the surface needs to be that large, but wait. So far the asteroid does show up and it’s not big enough:
Let’s think out this adjust thing. The asteroid raw data spans from -4 to 4 in both x and y. Let’s change adjust:
def adjust(self, point):
center_adjustment = vector2(4, 4)
return (point + center_adjustment) * 4
Now we have the asteroid range from 0,0 to 8,8 in raw form. Times four, 0 through 32. Let’s bump it to 16:
def adjust(self, point):
center_adjustment = vector2(4, 4)
return (point + center_adjustment) * 16
def prepare_surface(self):
surface = pygame.Surface((128, 128))
surface.set_colorkey((0, 0, 0))
adjusted = list(map(self.adjust, raw_rocks[0]))
pygame.draw.lines(surface, "white", False, adjusted, 3)
return surface
That gives me about what I was wanting:
I’ve unquestionably been hacking. I’m distracted by matters around the house or something. But this isn’t bad and definitely proves the concept. Let’s make it move while we’re at it.
Asteroid speed is 100 in the other game, we’ll try that here.
With the following, we have motion:
# u - universal constants
...
ASTEROID_SPEED = pygame.Vector2(100,0)
#main
...
ship = Ship(pygame.Vector2(u.SCREEN_SIZE / 2, u.SCREEN_SIZE / 2))
asteroid = Asteroid()
...
screen.fill("midnightblue")
ship.draw(screen)
asteroid.draw(screen)
...
ship.move(dt)
asteroid.move(dt)
...
class Asteroid:
def __init__(self):
self.position = vector2(u.SCREEN_SIZE/2, u.SCREEN_SIZE/2)
self.surface = self.prepare_surface()
rotation = random.randint(0,360)
self.velocity = u.ASTEROID_SPEED.rotate(rotation)
def move(self, dt):
self.position += self.velocity*dt
self.position.x = self.position.x % u.SCREEN_SIZE
self.position.y = self.position.y % u.SCREEN_SIZE
And we have a moving asteroid:
I think we’ll wrap it up here. What, if anything, have I learned?
I haven’t added a single test, but there’s not much to test.
I think this version of adjust
is better than the one on ship. They could both be static, combined into one, and might really want to belong on some kind of surface-making object. The method itself is a good candidate for static no matter where you put it, since it really belongs on Point or Vector or something.
There’s a lot of duplication between ship and asteroid, enough to make me think that there’s room for common moving code and probably room for a surface builder of some kind. I am tempted toward inheriting some common methods but I’m not sure I could stand the abuse from Hill were I to do that. We’ll see, there are many opportunities between now and anything near to done.
Overall, we have a moving asteroid in about 60 lines of code counting the data. Seems like a good bit of hacking for an afternoon.
See you next time!