preface
Last article It mainly introduces the in alien invasion, adds a play button and resets the game. In addition, when players play, they improve the level of the game and first modify the speed of the spacecraft. This paper introduces the last part of the project - scoring. First of all, let's introduce the implementation of display score.
next, we implement a scoring system to track players' scores in real time and display the highest score, current level and the number of remaining ships.
score is a statistical information of the game, so we add a score attribute in GameStates:
def reset_stats(self): """Initializes statistics that may change during game operation""" self.ships_left = self.ai_settings.ship_limit self.score = 0
in order to reset the score every time we start the game, we are in rect_stats() instead of__ init__ Initialize score in ().
1. Show score
to display scores on the screen, we first create a new class Scoreboard. At present, this class only displays the current score, but we will also use it later to display the highest score, level and the number of remaining ships. The following is the first half of this class, which is saved as the file scoreboard.py. The specific file directory is as follows:
next, we implement the first part of the Scoreboard class:
import pygame.font class Scoreboard(): """Class that displays score information""" def __init__(self, ai_settings, screen, stats): """Initialize scorekeeping attributes.""" self.screen = screen self.screen_rect = screen.get_rect() self.ai_settings = ai_settings self.stats = stats # Font settings for scoring information. self.text_color = (30, 30, 30) self.font = pygame.font.SysFont(None, 48) # Prepare initial score image self.prep_score()
since the Scoreboard class displays text on the screen, we first import the module pygame.font. Next, we are__ init__ () contains formal parameter ai_settings, screen, and satas, so that it can report the values we track. Then, we set the text color and instantiate a font object.
to convert the text to be displayed into an image, we call prep_score(), which is defined as follows:
def prep_score(self): """Convert the score to a rendered image""" score_str = str(self.stats.score) self.score_image = self.font.render(score_str, True, self.text_color, self.ai_settings.bg_color) # Place the score in the upper right corner of the screen self.score_rect = self.score_image.get_rect() self.score_rect.right = self.screen_rect.right - 20 self.score_rect.top = 20
in prep_ In score (), we first convert the digital value stats.score into a string, and then pass this string to render() which creates the image. In order to clearly display the score on the screen, we passed the screen background color and text color to render().
we put the scores in the upper right corner of the screen and extend them to the left when the score increases to make the number wider. To ensure that the score is always anchored on the right side of the screen, we created a named score_rect of rect, so that its right edge is 20 pixels away from the right edge of the screen, and its upper edge is also 20 pixels away from the upper edge of the screen.
finally, we create the method show_score() is used to display the rendered score image:
def show_score(self): """Show score on screen""" self.screen.blit(self.score_image, self.score_rect)
this method displays the score image on the screen and places it on the score_rect the specified location.
2. Create scoreboard
to show the score, we are in alien_ Create a Scoreboard instance in invasion.py:
import sys import pygame from settings import Settings from ship import Ship import game_functions as gf from pygame.sprite import Group from alien import Alien from game_stats import GameStats from button import Button from scoreboard import Scoreboard def run_game(): # Initialize the game and create a screen object pygame.init() ai_settings = Settings() screen = pygame.display.set_mode((ai_settings.screen_width, ai_settings.screen_height)) pygame.display.set_caption("Alian Invasion") # Create play button play_button = Button(ai_settings, screen, "Play") # Create an instance to store game statistics stats = GameStats(ai_settings) sb = Scoreboard(ai_settings, screen, stats) # Create a spaceship, a bullet group, and an alien group ship = Ship(ai_settings, screen) # Create a group for storing bullets bullets = Group() aliens = Group() # Create alien groups # alien = Alien(ai_settings, screen) gf.create_fleet(ai_settings, screen, ship, aliens) # Start the main cycle of the game while True: # Monitor keyboard and mouse events gf.check_events(ai_settings, screen, stats, play_button, ship, aliens, bullets) if stats.game_active: ship.update() gf.update_bullets (ai_settings, screen, ship, aliens, bullets) gf.update_aliens(ai_settings, stats, screen, ship, aliens, bullets) gf.update_screen(ai_settings, screen, stats, sb, ship, aliens, bullets, play_button) run_game()
we import the newly created class Scoreboard and create a Scoreboard instance named sb after creating the instance stats. Next, we pass sb to update_screen() enables it to display scores on the screen.
to display the score, update_ The screen () is modified as follows:
def update_screen(ai_settings, screen, stats, sb, ship, aliens, bullets, play_button): """Update the image on the screen and switch to a new screen""" # Redraw the screen each time you cycle screen.fill(ai_settings.bg_color) # Redraw all bullets behind ships and aliens for bullet in bullets.sprites(): bullet.draw_bullet() ship.blitme() aliens.draw(screen) # Show score sb.show_score() # If the game is inactive, draw the play add button if not stats.game_active: play_button.draw_button() # Make recently drawn screens visible pygame.display.flip()
we're updating_ sb is added to the parameter list of screen (), and show_ is called before drawing the play button. score.
if we are running this game, you will see 0 in the upper right corner of the screen (at present, we just want to make sure that the score appears in the right place before further developing the scoring system). The score effect before the game is as follows:
let's specify the value of each alien!
3. Update scores when aliens are destroyed
in order to display the score on the screen in real time, whenever an alien is hit, we update the value of stats.score and call prep_score() updates the score image. But before again, we need to specify how many points players will get for each alien shot down:
def initialize_dymaic_settings(self): """Initialize settings that change as the game progresses""" self.ship_speed_factor = 1.5 self.bullet_speed_factor = 3 self.alien_speed_factor = 1 # fleet_ A direction of 1 means moving to the right, and a direction of - 1 means moving to the left self.fleet_direction = 1 # Scoring self.alien_points = 50
as the game progresses, we will increase the points of each alien value. To ensure that this value is reset every time we start a new game, we use initialize_ dynamic_ Set it in settings().
check_ bullet_ alien_ In collections(), the score is updated whenever the alien is shot down:
def check_bullet_alien_collisions(ai_settings, screen, stats, sb, ship, aliens, bullets): """Update the location of bullets and delete disappeared bullets""" collisions = pygame.sprite.groupcollide(bullets, aliens, True, True) if collisions: stats.score += ai_settings.alien_points sb.prep_score() if len(aliens) == 0: bullets.empty() ai_settings.increase_speed() create_fleet(ai_settings, screen, ship, aliens)
we update check_ bullet_ alien_ The definition of collections () contains the formal parameters stats and sb, so that it can update the score and scoreboard. When a bullet hits an alien, pygame returns a dictionary. We check whether the dictionary exists. If it exists, we add a point of alien value to the score. Next, we call prep_score() to create a new image showing the latest score.
we need to modify update_bullets(), ensuring that appropriate arguments are passed between functions:
def update_bullets(ai_settings, screen, stats, sb, ship, aliens, bullets): """Update the location of bullets and delete disappeared bullets""" # Update bullet location bullets.update() # Delete lost bullets for bullet in bullets.copy(): if bullet.rect.bottom <= 0: bullets.remove(bullet) check_bullet_alien_collisions(ai_settings, screen, stats, sb, ship, aliens, bullets)
in update_ In the definition of bullets (), you need to add the formal parameters stats and sb, and call check_ bullet_ alien_ You also need to pass the arguments stats and sb when you collect ().
We also need to modify the call to update_ in the main while loop. Code of bullets():
import sys import pygame from settings import Settings from ship import Ship import game_functions as gf from pygame.sprite import Group from alien import Alien from game_stats import GameStats from button import Button from scoreboard import Scoreboard def run_game(): # Initialize the game and create a screen object pygame.init() ai_settings = Settings() screen = pygame.display.set_mode((ai_settings.screen_width, ai_settings.screen_height)) pygame.display.set_caption("Alian Invasion") # Create play button play_button = Button(ai_settings, screen, "Play") # Create an instance to store game statistics stats = GameStats(ai_settings) sb = Scoreboard(ai_settings, screen, stats) # Create a spaceship, a bullet group, and an alien group ship = Ship(ai_settings, screen) # Create a group for storing bullets bullets = Group() aliens = Group() # Create alien groups # alien = Alien(ai_settings, screen) gf.create_fleet(ai_settings, screen, ship, aliens) # Start the main cycle of the game while True: # Monitor keyboard and mouse events gf.check_events(ai_settings, screen, stats, play_button, ship, aliens, bullets) if stats.game_active: ship.update() gf.update_bullets (ai_settings, screen, stats, sb, ship, aliens, bullets) gf.update_aliens(ai_settings, stats, screen, ship, aliens, bullets) gf.update_screen(ai_settings, screen, stats, sb, ship, aliens, bullets, play_button) run_game()
call Update_ When bullets (), you need to pass the arguments stats and sb.
if we run this game now, the score will continue to increase. The specific effects are as follows:
4. Count the points of each alien eliminated into the score
at that time, there might be a bug in our code, that is, we missed some eliminated aliens. For example, if two bullets hit aliens in a cycle, or multiple aliens are hit at the same time because the bullets are wider, the player will only get the points of one destroyed alien. To fix this problem, let's adjust the way to detect bullets and alien collisions.
check_ bullet_ alien_ In collections (), the bullet colliding with aliens is a key in the dictionary collections; The value associated with each bullet is a list of aliens that the bullet hit. We traverse the dictionary collsions to ensure that the points of each alien destroyed are recorded in the score:
def check_bullet_alien_collisions(ai_settings, screen, stats, sb, ship, aliens, bullets): """Update the location of bullets and delete disappeared bullets""" collisions = pygame.sprite.groupcollide(bullets, aliens, True, True) if collisions: for aliens in collisions.values(): stats.score += ai_settings.alien_points sb.prep_score() if len(aliens) == 0: bullets.empty() ai_settings.increase_speed() create_fleet(ai_settings, screen, ship, aliens)
if the dictionary collections exists, we will traverse all the values in it. Don't forget that each value is a list of all aliens hit by the same bullet. For each list, the points of an alien are multiplied by the number of aliens contained in it, and the results are added to the current score. To test this, please change the bullet width to 300 pixels, verify that we get the points of each alien hit by a wider bullet, and then return the bullet width to the normal value.
5. Increase points
the game becomes more difficult every time the player increases one level, so the points of aliens should be higher at a higher level. To achieve this, we add some code to increase points when the game tempo is accelerated:
class Settings(): """Store all settings classes of alien invasion""" def __init__(self): """Initialize game settings""" # Screen settings self.screen_width = 1400 self.screen_height = 700 self.bg_color = (230, 230, 230) # Spacecraft settings self.ship_limit = 3 # Bullet settings self.bullet_width = 3 self.bullet_height = 15 self.bullet_color = 60, 60, 60 self.bullets_allowed = 6 # Alien settings self.fleet_drop_speed = 10 # What kind of speed to accelerate the pace of the game self.speedup_scale = 1.1 # Increase speed of alien points self.score_scale = 1.5 self.initialize_dymaic_settings() def initialize_dymaic_settings(self): """Initialize settings that change as the game progresses""" self.ship_speed_factor = 1.5 self.bullet_speed_factor = 3 self.alien_speed_factor = 1 # fleet_ A direction of 1 means moving to the right, and a direction of - 1 means moving to the left self.fleet_direction = 1 # Scoring self.alien_points = 50 def increase_speed(self): """Increase speed setting""" self.ship_speed_factor *= self.speedup_scale self.bullet_speed_factor *= self.speedup_scale self.alien_speed_factor *= self.speedup_scale self.alien_points = int(self.alien_points * self.score_scale) # print(self.alien_points)
we define the speed at which points increase and call it score_scale. A small tempo speed up makes the game very challenging quickly, but in order to make a significant change in scoring, you need to set the point increase speed to a larger value. Now, while speeding up the pace of the game, we have increased the points of each alien. To make the number of points an integer, we use the function int().
in order to display the points of aliens, we increase in the method of settings_ A print statement has been added to speed (). Therefore, now whenever we increase a level, we will see a new point value in the terminal window. What we need to pay attention to here is that we use print statement to test. When we are sure that our logic is correct, we should comment out this statement. Otherwise, it will affect the performance of the game and distract players.
6. Round the score
most arcade style shooting will display the score as an integral multiple of 10. Let's follow this principle in our scoring system. We will also format the score and add a thousand separator represented by commas to large numbers. We perform this modification in Scoreboard:
def prep_score(self): """Convert the score to a rendered image""" rounded_score = int(round(self.stats.score, -1)) score_str = "{:,}".format(rounded_score) self.score_image = self.font.render(score_str, True, self.text_color, self.ai_settings.bg_color) # Place the score in the upper right corner of the screen self.score_rect = self.score_image.get_rect() self.score_rect.right = self.screen_rect.right - 20 self.score_rect.top = 20
The function round() usually makes the decimal accurate to the number of decimal places after the decimal point, where the number of decimal places is specified by the second argument. However, if the second argument is specified as a negative number, round() rounds the circle to the nearest integer multiple of 10, 100, 1000, etc. At the same time, we also use a string format setting instruction, which allows Python to insert commas when converting values into strings, for example, output 1000000 instead of 1000000. If we play this game at this time, we will see an integer multiple score of 10, even if the score is very high, and separate them with commas. The specific effects are as follows:
summary
Last article It mainly introduces the in alien invasion, adds a play button and resets the game. In addition, when players play, they improve the level of the game and first modify the speed of the spacecraft. This paper introduces the last part of the project - scoring. This paper introduces the implementation of related functions in the scoring module, such as displaying scores, creating scoreboards, updating scores when aliens are eliminated, improving points and taking scores. However, only part of the code is written in this paper, because with the continuous expansion of the project, there are too many lines of code. In order to reduce the length of each article as much as possible, it is convenient for everyone to read and control the reading time of the article to about 20 minutes as much as possible. However, the accuracy of the code must be correct and can run! Therefore, I hope you can read it carefully, write the code carefully, and understand the in-depth meaning, so as to maximize the value of this project. In fact, this project is already very typical, and the code is everywhere. However, if you simply paste and copy, it will not be of any value to your knowledge learning. You still have to follow it, and then you should know the meaning of each line of code or which knowledge point we introduced earlier. Only in this way can this project play a different value, I hope you will study hard and lay a solid foundation of basic knowledge. Python is a language that pays attention to practical operation. It is the simplest and the best entry among many programming languages. When you learn the language, it's easier to learn java, go and C. Of course, Python is also a popular language, which is very helpful for the implementation of artificial intelligence. Therefore, it is worth your time to learn. Life is endless and struggle is endless. We work hard every day, study hard, and constantly improve our ability. I believe we will learn something. come on. In addition, I'm very happy. 2021s11 hero League global finals. Congratulations to EDG for winning the game, beating DK 3-2 and winning the championship. Happy!!! We are champions, hahaha!!!!