There are many basketball games on the Internet. Here we use pygame to write one. There is a shooter and a defender in the game. The shooter dribbled the ball to avoid defense, jumped up and shot, and scored a point. The closer the shooter is to the basket, the higher the shooting accuracy, but the closer he is to the basket, the more likely he is to meet the defender. If he does, the game is over. Below is the effect picture of the game.
The background of the game is the basketball court, as shown in the figure above. There are three roles, one for shooter, one for defender and one for basketball, which are respectively defined by class. The character animation modeling adopts match man, because the match man modeling is easy to find, even if it is not difficult to draw one by yourself. Unfortunately, my drawing ability is too poor. I can only pull out the shape frame by frame from a video. All graphic backgrounds should be set to transparent. All figures of the three roles are as follows:
The shooter dribbles with 4 black shapes, frame number 0-3. When you press the space bar, the jump shot will be started, and the frame number will be changed to 4. The jump shot has 12 black shapes, frame number 4-15. All shapes are used to realize the animation of shooter dribble and jump shot. In the previous blog post "dribbling in basketball game save pictures of each frame with a list", it can be seen that under the condition of four graphics per second, four shapes can complete the dribbling animation. Note that the ball is also a part of the shape. However, in the case of 4 graphics per second, it is impossible to use only 4 graphics for jump shot animation. After a try, 4 graphics per second, I feel that 12 graphics should be used, that is, it takes 12 * \ 0.25 seconds = 3 seconds for jump shot from take-off to fall, so as to have a satisfactory animation effect. The 12 figures of the jump shot are a bit of a makeshift, but you can still see the animation effect. If you draw the 12 figures carefully, the effect may be better. Note that there is basketball in frames 4, 5 and 6 of the jump shot, and there is no basketball in the back frame. At an appropriate time (in this example, in frame 8), the basketball character will appear above the shooter and move to the backboard from this as the starting point. He will touch the backboard in frame 13, and the ball will move downward in frames 14 and 15. If he hits the shot, he will directly fall into the blue, and if he doesn't hit the shot, he will fall from the side. Basketball has only one figure.
The first problem to be solved is when you can shoot and when you can't shoot. There are various rules for shooting in the online shooting game. The rules of the game are: the farther away from the basket, the more inaccurate the shooting is. When shooting at a certain point, the shooting is irregular, or random, but the probability of hitting is a fixed value. Set the distance from the shooting point to the basket as l, let n=(L//100) take an integer, and use the random number generator to generate a random integer between 1 and n+1. If the specified random number is 1, it will be hit, and other random integers will not be hit. If the distance from the point to the basket frame is y < 100, n = 0, the hit rate is 100%; If 200 > L > 99, n = 1, the hit rate is 50%; For example, 300 > L > 199, n = 2, the hit rate is 33%, and so on.
The defender has only two yellow shapes, which seems to be a little less, which is barely enough in this case. When the distance between the defender and the shooter is greater than 200, the defender retreats to the initial position of defense. Less than 200, and the shooter is dribbling, and the defender approaches the defense, that is, the defender moves a certain distance towards the shooter (should be an integer). If he meets the shooter, the game ends. The so-called face, that is, the defender moves along the line between the defender and the shooter. In this way, the line L and the difference DX and Dy between the defender and the shooter along the X and Y axes form a right triangle. If the defender moves dx1 along the x-axis and dy1 along the y-axis every frame, only dx1/dy1=dx/dy, the defender can move towards the shooter. If dy1=7, then dx1=7dx/dy. However, if dy is 0, an error divided by 0 will be generated. To avoid this situation, judge the size of DX and Dy first. If DX < Dy, use the above formula; otherwise, dx1=7, dy1=7dy/dx. Note that DX and Dy cannot be 0 at the same time, because before it is 0 at the same time, the shooter and the defender will approach and collide, leading to the end of the game. In this way, the moving distance in different directions may be different. In the above example, the maximum value is that both right angle sides are 7 and the distance is 9.899. Only the integer can be taken as 9. If the smaller right angle side is 0, the distance is 7. In addition, the increment along the X and Y axes can only be integers, so there is also an error in the direction.
The following is the whole program of the game, with detailed comments. It should be easier to understand the program. The level is limited, and there is inevitably some thoughtlessness. Criticism and correction are welcome. Only the copy shell source program can not run correctly. You need to make all the shapes of shooters and defenders, ball shapes and background basketball court, and put them in the folder where the source program is located. The source program and all images will be packaged and uploaded, which can be downloaded by readers in need. When playing the game, because the shooter moves with the mouse, when opening the program or playing the game again, you must move the mouse to the outer boundary of the program window to avoid the collision between the program and the defender at the beginning, resulting in the end of the game.
import pygame import math import random import os class Ball(): #Basketball def __init__(self,screen): #screen is the main form of the game and an instance of Surface class self.screen=screen b=pygame.image.load('b.png').convert_alpha() #Get basketball graphics r=b.get_rect() self.p=pygame.transform.scale(b,(r.width//2. R.height / / 2)) # zoom out self.x,self.y,self.xi,self.yi=0,0,0,0#(x,y) basketball coordinates, (xi,yi) is the increment between two basketball positions self.frameNum=9 #Basketball frame number (1-8), = 9, basketball is not visible self.mark=0 #Whether the shooting is successful or not, = 0 is not successful, = 1 is successful self.score=0 #Number of shots (score) def draw(self): #Call the main program to realize basketball animation if self.frameNum==9: #Basketball frame number = 9, basketball is not visible return if self.frameNum==1: #The first frame calculates the necessary data. The coordinates of the next sentence (self.x,self.y) are the starting point of the ball dx,dy=(400-self.x),(40-self.y) #The coordinate (400530) point is the point where the ball hits the backboard self.xi=dx//6 # basketball increment along the x-axis from the starting point to the backboard self.yi=dy//6 # basketball increment along the y-axis from the starting point to the backboard dist=math.sqrt((dx**2)+(dy**2)) #Distance from shooting point to backboard n=int(dist//The smaller the 100) # divisor, the lower the total hit rate if random.randint(1,n+1)==1: #The random number is 1, and n+1 avoids dist < 100 as 0 self.mark=1 #Hit marked as 1 else: self.mark=0 #If it is not in the middle, it is 0 if self.frameNum>=1 and self.frameNum<6: #From frame 1 to frame 5, the ball advances in this way self.x+=self.xi #Basketball increases by 1 increment along the x axis every frame self.y+=self.yi #Basketball increases by 1 increment along the y-axis every frame self.frameNum+=1 elif self.frameNum==6: #In this frame, the ball will hit the backboard. The landing point of hitting the backboard should be accurately controlled self.x=400 #x coordinate of the ball hitting the backboard self.frameNum+=1 if self.mark==1: #Hit, the basketball landing point is close to the basket in the y-axis direction self.y=90 else: #If you miss the shot, the y-axis direction of the basketball landing point is far from the basket self.y=70 else: #The two points where the basketball falls, frames 7 and 8 if self.mark==0: #When the ball is not hit, the ball moves along the x-axis in addition to falling, and the ball falls from both sides of the basket if self.xi>=0: #If the ball moves from left to right, in the last two frames, the ball continues to move from left to right along the x-axis self.x+=30 else: self.x-=30 #Otherwise, in the last two frames, the ball continues to move from right to left along the x-axis self.y+=25 #If the x coordinate of the shot remains unchanged, that is, the ball falls directly through the basket self.frameNum+=1 self.screen.blit(self.p, (self.x, self.y)) #Draw basketball at the specified position on the screen if self.frameNum==9 and self.mark==1: #When all actions of the ball are completed, judge whether the score is increased by 1 self.score+=1 class Guard(): #Defenders def __init__(self,screen): ##screen is the main form of the game and an instance of Surface class self.screen=screen self.images=[] for n in range(2): #Save 2 images to the list p = pygame.image.load(str(n+16)+'.png').convert_alpha()#The file name is 16 png,17. png r=p.get_rect() p = pygame.transform.scale(p, (r.width//6. R.height / / 6)) # resize the image self.images.append(p) self.frameNum=0 #Frame number, 0-1 self.x,self.y=400,300 #The initial coordinates of the defender in the form self.PlayerX,self.PlayerY=0,0 #At this time, the shooter coordinates self.PlayerFrameNum=0 #The shooter's frame number self.rect=None#Call blit to draw the graph and return rect to record the graph in screen coordinates and graph width and height to detect collision def draw(self): #Call the main program to realize the defender animation p=self.images[self.frameNum] #Take out the current frame graph if self.PlayerX-self.x<0: #Facing the shooter p=pygame.transform.flip(p,True,False) dx,dy=self.PlayerX-self.x,self.PlayerY-self.y #The difference dx and dy between the defender and the shooter along the x and y axes dist=math.sqrt((dx**2)+(dy**2)) #Calculate the distance between the shooter and the defender dx1,dy1=0,0 #The defender moves dx1 along the x axis and dy1 along the y axis every frame if dist>200: #If the distance from the shooter is > 200, return to the initial point self.x,self.y=400,300 elif self.PlayerFrameNum<4: #If the shooter does not shoot, approach the shooter, if the shooter shoots, the position of the defender remains unchanged if abs(dx)<abs(dy): #Ensure that abs(dy) is not 0, so that the next sentence dx/dy will not be divided by 0 d=abs(dx/dy) dy1=7 #If the long side of the rectangle is 7, dx1=int((dy1*d)//1) #dx1 may be: 0, 1, 2, 3, 4, 5, 6, 7 else: #Ensure that abs(dx) is not 0, so that the next sentence dy/dx will not be divided by 0 d=abs(dy/dx) dx1=7 #If the long side of the rectangle is 7, dy1=int((dx1*d)//1) #dy1 may be: 0, 1, 2, 3, 4, 5, 6, 7 if dx<0: #Get the sign of dx dx1=-dx1 if dy<0: #Get the sign of dy dy1=-dy1 self.x+=dx1 #Defender movement self.y+=dy1#The following sentence returns rect to detect collision. Its attributes X and y are the coordinates of the figure in the game window, and width and height are the width and height of the figure self.rect=self.screen.blit(p,(self.x,self.y)) #Draw the defender at the specified position on the screen self.frameNum+=1 if self.frameNum==2: self.frameNum=0 class Player(): #Shooting hand def __init__(self,screen): #screen is the main form of the game and an instance of Surface class self.screen=screen self.images=[] for n in range(16): #Save 16 frame images (including dribble and jump shot images) to the list p = pygame.image.load(str(n)+'.png').convert_alpha()#The file name is 1 png,2. png... r=p.get_rect() p = pygame.transform.scale(p, (r.width//6. R.height / / 6)) # resize the image self.images.append(p) self.frameNum=0 #Frame number, dribble 0 to 3, jump shot 4 to 15 self.x,self.y=0,0 #Coordinates of the image on the form self.mouseX,self.mouseY=0,0 #The mouse coordinate value self.jumpUpOrDown=-10 #After pressing the space bar, the shooter jumps up, and the initial value is negative. Fall after reaching the highest point, which is a positive number self.rect=None#Call blit to draw the graph and return rect to record the graph in screen coordinates and graph width and height to detect collision def dribble(self): #Dribble animation p=self.images[self.frameNum] if self.mouseX-self.x<0: #Mouse oriented p=pygame.transform.flip(p,True,False) self.x,self.y=self.mouseX,self.mouseY #Shooter coordinates = mouse coordinates if self.x<1: #The control shooter must be on the basketball court self.x=1 if self.x+90>width: self.x=width-90 if self.y<230: self.y=230 if self.y+120>height: self.y=height-120 self.rect=self.screen.blit(p,(self.x,self.y)) #Draw a graph at the specified position and return rect self.frameNum+=1 if self.frameNum==4: self.frameNum=0 def jumpShot(self): #Jump shot animation p=self.images[self.frameNum] if self.x>width/2: #Facing the backboard p=pygame.transform.flip(p,True,False) self.screen.blit(p, (self.x, self.y)) #The initial position of jump shot is the position when the dribble turns to jump shot self.y+=self.jumpUpOrDown #After that, it goes up first (the y value decreases), and then goes down to the highest point self.frameNum+=1 if self.frameNum==9: #Start falling, and the falling value is positive self.jumpUpOrDown=10 if self.frameNum==16: #=16, jump shot end, transfer ball self.frameNum=0 self.jumpUpOrDown=-10 pygame.init() os.environ['SDL_VIDEO_WINDOW_POS']="%d,%d"%(200,40) #The number of points from the left and top of the game window is 200,40 size = width, height = 800,600 #Create game window size screen = pygame.display.set_mode(size) pygame.display.set_caption("Pitchers dribble and jump shot") #Set window title bg_img = pygame.image.load("Basketball court 1.png").convert() #Background basketball court image fclock = pygame.time.Clock() #Create a clock to control the frequency fps = 4 #Define refresh rate player=Player(screen) #Examples of Shooters ball=Ball(screen) #Basketball examples guard=Guard(screen) #Defender class instance font1 = pygame.font.SysFont('Song style', 50, True) #Create font gameOver=False #Whether the game is over, not at the beginning running = True #Whether the program ends and runs initially while running: for event in pygame.event.get(): if event.type == pygame.QUIT: #Handle exit events running = False #Program end if event.type == pygame.MOUSEMOTION: #Mouse movement event player.mouseX,player.mouseY=event.pos #Pass the mouse position to the shooter for dribbling if event.type == pygame.KEYUP: #Lift the event after pressing the key to avoid not lifting the long key if event.key == pygame.K_SPACE: #Press the space bar and lift it up if player.frameNum<4: #If in dribbling state, turn to shooting state player.frameNum=4 #It is already in shooting status and will not be processed if event.key == pygame.K_r and gameOver==True: #Press the r key and lift it up to play the game again gameOver=False ball.score=0 screen.blit(bg_img, (0, 0)) #Draw basketball court background surface1=font1.render('score:'+str(ball.score),True,[255,0,0]) #Cannot display Chinese screen.blit(surface1, (20, 20)) #Display the number of goals (score) if gameOver==True: #If the game is over, the subsequent program will no longer be executed fclock.tick(fps) #fps is the number of frames per second, minus the program running time. In order to realize fps, it also needs to delay time continue if player.frameNum>=4: #If the shooter frame number > = 4, the shooter is making a jump shot player.jumpShot() if player.frameNum==8: #Frame 8 jump up without a ball in hand, the basketball will appear and start to rebound ball.frameNum=1 #The ball moves to the backboard frame 1 ball.x=player.x #The starting position of the ball moving towards the backboard ball.y=player.y else: #If the shooter's frame number is < 4, the shooter is dribbling player.dribble() ball.draw() #Basketball animation guard.PlayerX,guard.PlayerY=player.x,player.y #Pass the shooter's position to the defender guard.PlayerFrameNum=player.frameNum #Pass the shooter's frame number to the defender guard.draw() #Defensive player animation if player.frameNum<4: #Judge whether there is a collision with the defender only when the shooter dribbles the ball if player.rect.colliderect(guard.rect): #Detect whether there is a collision between the shooter and the defender gameOver=True #There is a collision and the game is over surface2=font1.render('if play again,press key r',True,[255,0,0]) screen.blit(surface2, (20, 100)) #If you continue to play, press r pygame.display.flip() #Refresh the game scene fclock.tick(fps) #fps is the number of frames per second, minus the program running time. In order to realize fps, it also needs to delay time pygame.quit()