CobraPy? CobraPew! Pew!
It has been a week and I had not really touched CobraPy my 80s-style python environemnt at all. UNTIL YESTERDAY.
So, how is it looking now? Like this, using assets from the AWESOME kenney.nl:
I have added:
- Support for music (you are listening to 80616-lunchip.xm)
- Support for sounds
- Some improvements to the sprite engine (reusing textures and such)
- Better keyboard support, or at least one that's more useful for games
- Fixed a bunch of bugs
- Added collision detection (did not make it to the video but it's there)
So let's go over the whole source code for that "game" and see how it works? Keep in mind that this code will look bizarre for your standard Python programmer because it's deliberately done in a ... "basic" style? Even in a BASIC style. Which means it aims to be more "structured programming" than what you are used to seeing.
Also, there are no guarantees that any of the APIs exposed will even exist tomorrow, since this is still in a prototyping phase and things will change.
import time
load_sprite("player", "assets/PNG/playerShip3_orange.png")
x = 100
y = 500
step = 3
move_sprite("player", x, y)
We created the intrepid player's ship, and put it "somewhere". Sprites are identified by a name. All sprite operations will use that name to know what sprite should be affected.
# A fleet of bad ships
fleet = [
[f"enemy-1-{x}" for x in range(7)],
[f"enemy-2-{x}" for x in range(7)],
[f"enemy-3-{x}" for x in range(7)],
[f"enemy-4-{x}" for x in range(7)],
]
for invader in fleet[0]:
load_sprite(invader, "assets/PNG/Enemies/enemyBlack1.png")
for invader in fleet[1]:
load_sprite(invader, "assets/PNG/Enemies/enemyBlue2.png")
for invader in fleet[2]:
load_sprite(invader, "assets/PNG/Enemies/enemyGreen3.png")
for invader in fleet[3]:
load_sprite(invader, "assets/PNG/Enemies/enemyRed4.png")
Again, just a few ships with different looks.
def move_fleet(x, y):
"""Move fleet so the left-top alien is in position x, y"""
for inv_y, row in enumerate(fleet):
for inv_x, invader in enumerate(row):
move_sprite(invader, x + 90 * inv_x, y + 90 * inv_y)
fleet_x = 50
fleet_y = 50
fleet_step_x = 1
fleet_step_y = 5
A function to move the fleet as a whole, and some info about it, location and speed.
load_sprite("laser", "assets/PNG/Lasers/laserBlue01.png")
load_sound("laser", "assets/Audio/laserRetro_004.ogg")
laser_last_shot = time.time()
laser_x = -100
laser_y = 0
def shoot():
global laser_x, laser_y, x, y, laser_last_shot
play_sound("laser")
laser_x = x
laser_y = y
laser_last_shot = time.time()
Same for our lonely bullet, but we have a couple of new things. With load_sound
we load into the program a
sound (surprise!) and with play_sound
it's played. Just like sprites, they are identified by name.
We keep track of when we shoot because this is a ship, not a machinegun, Jim!
def check_hit():
global laser_last_shot
t1 = time.time()
global laser_x
for row in fleet:
for invader in row:
if check_collision("laser", invader):
laser_x = -100
laser_last_shot = 0
Collision detection! If the bullet hits an invader ... well, we can't make it explode yet, but we move the bullet out and allow the user to shoot again, at least.
load_music_stream("background", "80616-lunchip.xm")
play_music_stream("background")
Just load and play a nice chiptune! As usual, music is identified by a label, so we can have more than one and play the one we want.
def gameloop():
global x, fleet_x, fleet_y, fleet_step_x, fleet_step_y, laser_y
The gameloop
function is special. Whatever you put here CobraPy will try to run it 60 times a second.
No faster, maybe slower if your gameloop
takes too long. So this is where you do things like update
the screen and interact with the user. You know ... a game loop.
if is_pressed(114) and x < 720: # right arrow
x += step
if is_pressed(113) and x > 0: # left arrow
x -= step
if is_pressed(38): # a
if time.time() - laser_last_shot > 1:
shoot()
User interaction! Basically is_pressed
takes a key identifier (nice constants coming soonish) and tells you
if it's pressed or not. So, if right-arrow is pressed, increase x
(within limits), if left-arrow is, decrease it (within limits). If "a" is
pressed and you have not shot for a second, shoot.
move_sprite("player", x, 500)
Well, that's why we increased / decreased it, right?
fleet_x += fleet_step_x
move_fleet(fleet_x, fleet_y)
if fleet_x < 50 or fleet_x > 150:
fleet_step_x = -fleet_step_x
fleet_y += fleet_step_y
The fleet moves to the right, then to the left, and at every turn, down. Does it remind you of any game you've seen?
laser_y -= step
move_sprite("laser", laser_x, laser_y)
Bullet go up.
check_hit()
Enemy go boom. Eventually.