Introduction to the game
Use pycharm to develop the little game "ow big cat run". Is a relatively simple cool run game, only 5 levels.
Introduction to play
Press the space bar control can let the cat jump, to avoid bullets and dragons at the same time. There will be a high score list after the end.
Game Preview
Game development process
1, Material preparation
2, Programming
1. Initialize the game and set the game start interface
pygame.init() audio_init() screen = pygame.display.set_mode((800,600),0,32) pygame.display.set_caption("Ow, meow, run!") font = pygame.font.Font(None, 22) font1 = pygame.font.Font(None, 40) framerate = pygame.time.Clock() upImageFilename = 'game_start_up.png' downImageFilename = 'game_start_down.png' #Create button object button = Button(upImageFilename,downImageFilename, (400,500)) interface = pygame.image.load("first.png")
2. In the game, there are several kinds of elves: oudamiao, dragon, fire, explosion animation and fruit. These sprites are all instantiated objects of MySprite class. We integrated these common classes and modules into MyLibrary.py.
The code of MyLibrary.py is as follows:
# MyLibrary.py import sys, time, random, math, pygame from pygame.locals import * # prints text using the supplied font def print_text(font, x, y, text, color=(255,255,255)): imgText = font.render(text, True, color) screen = pygame.display.get_surface() #req'd when function moved into MyLibrary screen.blit(imgText, (x,y)) # MySprite class extends pygame.sprite.Sprite class MySprite(pygame.sprite.Sprite): def __init__(self): pygame.sprite.Sprite.__init__(self) #extend the base Sprite class self.master_image = None self.frame = 0 self.old_frame = -1 self.frame_width = 1 self.frame_height = 1 self.first_frame = 0 self.last_frame = 0 self.columns = 1 self.last_time = 0 self.direction = 0 self.velocity = Point(0.0,0.0) #X property def _getx(self): return self.rect.x def _setx(self,value): self.rect.x = value X = property(_getx,_setx) #Y property def _gety(self): return self.rect.y def _sety(self,value): self.rect.y = value Y = property(_gety,_sety) #position property def _getpos(self): return self.rect.topleft def _setpos(self,pos): self.rect.topleft = pos position = property(_getpos,_setpos) def load(self, filename, width, height, columns): self.master_image = pygame.image.load(filename).convert_alpha() self.frame_width = width self.frame_height = height self.rect = Rect(0,0,width,height) self.columns = columns #try to auto-calculate total frames rect = self.master_image.get_rect() self.last_frame = (rect.width // width) * (rect.height // height) - 1 def update(self, current_time, rate=30): #update animation frame number if current_time > self.last_time + rate: self.frame += 1 if self.frame > self.last_frame: self.frame = self.first_frame self.last_time = current_time #build current frame only if it changed if self.frame != self.old_frame: frame_x = (self.frame % self.columns) * self.frame_width frame_y = (self.frame // self.columns) * self.frame_height rect = Rect(frame_x, frame_y, self.frame_width, self.frame_height) self.image = self.master_image.subsurface(rect) self.old_frame = self.frame def __str__(self): return str(self.frame) + "," + str(self.first_frame) + \ "," + str(self.last_frame) + "," + str(self.frame_width) + \ "," + str(self.frame_height) + "," + str(self.columns) + \ "," + str(self.rect) #Point class class Point(object): def __init__(self, x, y): self.__x = x self.__y = y #X property def getx(self): return self.__x def setx(self, x): self.__x = x x = property(getx, setx) #Y property def gety(self): return self.__y def sety(self, y): self.__y = y y = property(gety, sety) def __str__(self): return "{X:" + "{:.0f}".format(self.__x) + \ ",Y:" + "{:.0f}".format(self.__y) + "}"
Create several sprite groups and write some sprites into them
#Create a sprite group group = pygame.sprite.Group() group_exp = pygame.sprite.Group() group_fruit = pygame.sprite.Group() #Create monster spirit dragon = MySprite() dragon.load("dragon.png", 260, 150, 3) dragon.position = 100, 230 group.add(dragon) #Create explosion animation explosion = MySprite() explosion.load("explosion.png",128,128,6) #Create player Wizard player = MySprite() player.load("sprite.png", 100, 100, 4) player.position = 400, 270 group.add(player) #Create bullet Genie arrow = MySprite() arrow.load("flame.png", 40, 16, 1) arrow.position = 800,320 group.add(arrow)
3. Define a rolling map class
class MyMap(pygame.sprite.Sprite): def __init__(self,x,y): self.x = x self.y = y self.bg = pygame.image.load("background.png").convert_alpha() def map_rolling(self): if self.x < -300: self.x = 300 else: self.x -=5 def map_update(self): screen.blit(self.bg, (self.x,self.y)) def set_pos(x,y): self.x =x self.y =y
Create map objects
bg1 = MyMap(0,0) bg2 = MyMap(300,0)
The way to call update and rolling in the program can make the map scroll up indefinitely.
bg1.map_update() bg2.map_update() bg1.map_rolling() bg2.map_rolling()
4. Define a button class. When the mouse passes by, it will become gray.
Play the pressed sound and background music of the game when the button is pressed
class Button(object): def __init__(self, upimage, downimage,position): self.imageUp = pygame.image.load(upimage).convert_alpha() self.imageDown = pygame.image.load(downimage).convert_alpha() self.position = position self.game_start = False def isOver(self): point_x,point_y = pygame.mouse.get_pos() x, y = self. position w, h = self.imageUp.get_size() in_x = x - w/2 < point_x < x + w/2 in_y = y - h/2 < point_y < y + h/2 return in_x and in_y def render(self): w, h = self.imageUp.get_size() x, y = self.position if self.isOver(): screen.blit(self.imageDown, (x-w/2,y-h/2)) else: screen.blit(self.imageUp, (x-w/2, y-h/2)) def is_start(self): if self.isOver(): b1,b2,b3 = pygame.mouse.get_pressed() if b1 == 1: self.game_start = True bg_sound.play_pause() btn_sound.play_sound() bg_sound.play_sound() def replay_music(): bg_sound.play_pause() bg_sound.play_sound()
5. Define a class for controlling sound and a method for initial audio
def audio_init():#Initialize audio global hit_au,btn_au,bg_au,bullent_au pygame.mixer.init() hit_au = pygame.mixer.Sound("exlposion.wav") btn_au = pygame.mixer.Sound("button.wav") bg_au = pygame.mixer.Sound("background.ogg") bullent_au = pygame.mixer.Sound("bullet.wav") class Music():#Control the playback and pause of sound def __init__(self,sound): self.channel = None self.sound = sound def play_sound(self): self.channel = pygame.mixer.find_channel(True) self.channel.set_volume(0.5) self.channel.play(self.sound) def play_pause(self): self.channel.set_volume(0.0) self.channel.play(self.sound)
6. Write the function to reset the bullet and issue the bullet continuously
Update bullet
if not game_over: arrow.X -= arrow_vel if arrow.X < -40: reset_arrow()
Reset bullet function
def reset_arrow(): y = random.randint(270,350) arrow.position = 800,y bullent_sound.play_sound()
7. In order to move the fruits, you need to traverse the fruits in group fruit, and then move them in turn. It is also necessary to judge that the player eats the fruit, the fruit disappears and the player's points increase.
#Traverse the fruit to move it for e in group_fruit: e.X -=5 collide_list = pygame.sprite.spritecollide(player,group_fruit,True) score +=len(collide_list)
8. Define some variables and write the game's loop system
arrow_vel = 10.0 game_over = False you_win = False player_jumping = False jump_vel = 0.0 player_start_y = player.Y player_hit = False monster_hit = False p_first = True m_first = True best_score = 0 global bg_sound,hit_sound,btn_sound,bullent_sound bg_sound=Music(bg_au) hit_sound=Music(hit_au) btn_sound=Music(btn_au) bullent_sound =Music(bullent_au) game_round = {1:'ROUND ONE',2:'ROUND TWO',3:'ROUND THREE',4:'ROUND FOUR',5:'ROUND FIVE'} game_pause = True index =0 current_time = 0 start_time = 0 music_time = 0 score =0 replay_flag = True #loop bg_sound.play_sound() best_score = data_read() while True: framerate.tick(60) ticks = pygame.time.get_ticks() for event in pygame.event.get(): if event.type == pygame.QUIT: pygame.quit() sys.exit() keys = pygame.key.get_pressed() if keys[K_ESCAPE]: pygame.quit() sys.exit() elif keys[K_SPACE]: if not player_jumping: player_jumping = True jump_vel = -12.0 screen.blit(interface,(0,0)) button.render() button.is_start() if button.game_start == True: if game_pause : index +=1 tmp_x =0 if score >int (best_score): best_score = score fd_2 = open("data.txt","w+") fd_2.write(str(best_score)) fd_2.close()
9. Write game detection, mainly as follows:
(1) Whether the player enters the next level
(2) Collision detection: whether the bullet hits the player, whether the bullet hits the monster, whether the player is chased by the monster, and whether the player is jumping
#Update sprite group if not game_over: group.update(ticks, 60) group_exp.update(ticks,60) group_fruit.update(ticks,60) #Loop background music music_time = time.clock() if music_time > 150 and replay_flag: replay_music() replay_flag =False #Draw sprite group group.draw(screen) group_fruit.draw(screen) if player_hit or monster_hit: group_exp.draw(screen) print_text(font, 330, 560, "press SPACE to jump up!") print_text(font, 200, 20, "You have get Score:",(219,224,22)) print_text(font1, 380, 10, str(score),(255,0,0)) if game_over: start_time = time.clock() current_time =time.clock()-start_time while current_time<5: screen.fill((200, 200, 200)) print_text(font1, 300, 150,"GAME OVER!",(240,20,20)) current_time =time.clock()-start_time print_text(font1, 320, 250, "Best Score:",(120,224,22)) if score >int (best_score): best_score = score print_text(font1, 370, 290, str(best_score),(255,0,0)) print_text(font1, 270, 330, "This Game Score:",(120,224,22)) print_text(font1, 370, 380, str(score),(255,0,0)) pygame.display.update() fd_2 = open("data.txt","w+") fd_2.write(str(best_score)) fd_2.close() pygame.quit() sys.exit()
The complete code of the game is as follows:
# -*- coding: utf-8 -*- import sys, time, random, math, pygame,locale from pygame.locals import * from MyLibrary import * #Reset bullet function def reset_arrow(): y = random.randint(270,350) arrow.position = 800,y bullent_sound.play_sound() #Define a rolling map class class MyMap(pygame.sprite.Sprite): def __init__(self,x,y): self.x = x self.y = y self.bg = pygame.image.load("background.png").convert_alpha() def map_rolling(self): if self.x < -300: self.x = 300 else: self.x -=5 def map_update(self): screen.blit(self.bg, (self.x,self.y)) def set_pos(x,y): self.x =x self.y =y #Define a button class class Button(object): def __init__(self, upimage, downimage,position): self.imageUp = pygame.image.load(upimage).convert_alpha() self.imageDown = pygame.image.load(downimage).convert_alpha() self.position = position self.game_start = False def isOver(self): point_x,point_y = pygame.mouse.get_pos() x, y = self. position w, h = self.imageUp.get_size() in_x = x - w/2 < point_x < x + w/2 in_y = y - h/2 < point_y < y + h/2 return in_x and in_y def render(self): w, h = self.imageUp.get_size() x, y = self.position if self.isOver(): screen.blit(self.imageDown, (x-w/2,y-h/2)) else: screen.blit(self.imageUp, (x-w/2, y-h/2)) def is_start(self): if self.isOver(): b1,b2,b3 = pygame.mouse.get_pressed() if b1 == 1: self.game_start = True bg_sound.play_pause() btn_sound.play_sound() bg_sound.play_sound() def replay_music(): bg_sound.play_pause() bg_sound.play_sound() #Define a method of data IO def data_read(): fd_1 = open("data.txt","r") best_score = fd_1.read() fd_1.close() return best_score #Define a class for controlling sound and a method for initial audio def audio_init(): global hit_au,btn_au,bg_au,bullent_au pygame.mixer.init() hit_au = pygame.mixer.Sound("exlposion.wav") btn_au = pygame.mixer.Sound("button.wav") bg_au = pygame.mixer.Sound("background.ogg") bullent_au = pygame.mixer.Sound("bullet.wav") class Music(): def __init__(self,sound): self.channel = None self.sound = sound def play_sound(self): self.channel = pygame.mixer.find_channel(True) self.channel.set_volume(0.5) self.channel.play(self.sound) def play_pause(self): self.channel.set_volume(0.0) self.channel.play(self.sound) #Main program part pygame.init() audio_init() screen = pygame.display.set_mode((800,600),0,32) pygame.display.set_caption("Ow, meow, run!") font = pygame.font.Font(None, 22) font1 = pygame.font.Font(None, 40) framerate = pygame.time.Clock() upImageFilename = 'game_start_up.png' downImageFilename = 'game_start_down.png' #Create button object button = Button(upImageFilename,downImageFilename, (400,500)) interface = pygame.image.load("first.png") #Create map objects bg1 = MyMap(0,0) bg2 = MyMap(300,0) #Create a sprite group group = pygame.sprite.Group() group_exp = pygame.sprite.Group() group_fruit = pygame.sprite.Group() #Create monster spirit dragon = MySprite() dragon.load("dragon.png", 260, 150, 3) dragon.position = 100, 230 group.add(dragon) #Create explosion animation explosion = MySprite() explosion.load("explosion.png",128,128,6) #Create player Wizard player = MySprite() player.load("sprite.png", 100, 100, 4) player.position = 400, 270 group.add(player) #Create bullet Genie arrow = MySprite() arrow.load("flame.png", 40, 16, 1) arrow.position = 800,320 group.add(arrow) #Define some variables arrow_vel = 10.0 game_over = False you_win = False player_jumping = False jump_vel = 0.0 player_start_y = player.Y player_hit = False monster_hit = False p_first = True m_first = True best_score = 0 global bg_sound,hit_sound,btn_sound,bullent_sound bg_sound=Music(bg_au) hit_sound=Music(hit_au) btn_sound=Music(btn_au) bullent_sound =Music(bullent_au) game_round = {1:'ROUND ONE',2:'ROUND TWO',3:'ROUND THREE',4:'ROUND FOUR',5:'ROUND FIVE'} game_pause = True index =0 current_time = 0 start_time = 0 music_time = 0 score =0 replay_flag = True #loop bg_sound.play_sound() best_score = data_read() while True: framerate.tick(60) ticks = pygame.time.get_ticks() for event in pygame.event.get(): if event.type == pygame.QUIT: pygame.quit() sys.exit() keys = pygame.key.get_pressed() if keys[K_ESCAPE]: pygame.quit() sys.exit() elif keys[K_SPACE]: if not player_jumping: player_jumping = True jump_vel = -12.0 screen.blit(interface,(0,0)) button.render() button.is_start() if button.game_start == True: if game_pause : index +=1 tmp_x =0 if score >int (best_score): best_score = score fd_2 = open("data.txt","w+") fd_2.write(str(best_score)) fd_2.close() #Judge whether the game is cleared if index == 6: you_win = True if you_win: start_time = time.clock() current_time =time.clock()-start_time while current_time<5: screen.fill((200, 200, 200)) print_text(font1, 270, 150,"YOU WIN THE GAME!",(240,20,20)) current_time =time.clock()-start_time print_text(font1, 320, 250, "Best Score:",(120,224,22)) print_text(font1, 370, 290, str(best_score),(255,0,0)) print_text(font1, 270, 330, "This Game Score:",(120,224,22)) print_text(font1, 385, 380, str(score),(255,0,0)) pygame.display.update() pygame.quit() sys.exit() for i in range(0,100): element = MySprite() element.load("fruit.png", 75, 20, 1) tmp_x +=random.randint(50,120) element.X = tmp_x+300 element.Y = random.randint(80,200) group_fruit.add(element) start_time = time.clock() current_time =time.clock()-start_time while current_time<3: screen.fill((200, 200, 200)) print_text(font1, 320, 250,game_round[index],(240,20,20)) pygame.display.update() game_pause = False current_time =time.clock()-start_time else: #Update bullet if not game_over: arrow.X -= arrow_vel if arrow.X < -40: reset_arrow() #Collision detection, whether the bullet hits the player if pygame.sprite.collide_rect(arrow, player): reset_arrow() explosion.position =player.X,player.Y player_hit = True hit_sound.play_sound() if p_first: group_exp.add(explosion) p_first = False player.X -= 10 #Collision detection, whether the bullet hit the monster if pygame.sprite.collide_rect(arrow, dragon): reset_arrow() explosion.position =dragon.X+50,dragon.Y+50 monster_hit = True hit_sound.play_sound() if m_first: group_exp.add(explosion) m_first = False dragon.X -= 10 #Collision detection, whether players are chased by monsters if pygame.sprite.collide_rect(player, dragon): game_over = True #Traverse the fruit to move it for e in group_fruit: e.X -=5 collide_list = pygame.sprite.spritecollide(player,group_fruit,True) score +=len(collide_list) #Pass the gate or not if dragon.X < -100: game_pause = True reset_arrow() player.X = 400 dragon.X = 100 #Check whether the player is in jumping state if player_jumping: if jump_vel <0: jump_vel += 0.6 elif jump_vel >= 0: jump_vel += 0.8 player.Y += jump_vel if player.Y > player_start_y: player_jumping = False player.Y = player_start_y jump_vel = 0.0 #Drawing background bg1.map_update() bg2.map_update() bg1.map_rolling() bg2.map_rolling() #Update sprite group if not game_over: group.update(ticks, 60) group_exp.update(ticks,60) group_fruit.update(ticks,60) #Loop background music music_time = time.clock() if music_time > 150 and replay_flag: replay_music() replay_flag =False #Draw sprite group group.draw(screen) group_fruit.draw(screen) if player_hit or monster_hit: group_exp.draw(screen) print_text(font, 330, 560, "press SPACE to jump up!") print_text(font, 200, 20, "You have get Score:",(219,224,22)) print_text(font1, 380, 10, str(score),(255,0,0)) if game_over: start_time = time.clock() current_time =time.clock()-start_time while current_time<5: screen.fill((200, 200, 200)) print_text(font1, 300, 150,"GAME OVER!",(240,20,20)) current_time =time.clock()-start_time print_text(font1, 320, 250, "Best Score:",(120,224,22)) if score >int (best_score): best_score = score print_text(font1, 370, 290, str(best_score),(255,0,0)) print_text(font1, 270, 330, "This Game Score:",(120,224,22)) print_text(font1, 370, 380, str(score),(255,0,0)) pygame.display.update() fd_2 = open("data.txt","w+") fd_2.write(str(best_score)) fd_2.close() pygame.quit() sys.exit() pygame.display.update()