ThePythonGameBook

learn Python. Create Games

User Tools

Site Tools


en:pygame:step020

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
en:pygame:step020 [2020/05/03 21:35]
Horst JENS ↷ Links adapted because of a move operation
en:pygame:step020 [2020/05/15 22:53] (current)
Horst JENS
Line 84: Line 84:
 View/​Edit/​Download the file directly in Github: https://​github.com/​horstjens/​ThePythonGameBook/​blob/​master/​pygame/​020_shooting_from_tank.py View/​Edit/​Download the file directly in Github: https://​github.com/​horstjens/​ThePythonGameBook/​blob/​master/​pygame/​020_shooting_from_tank.py
  
-//click reload in your browser if you see no code here:// 
-<​html>​ 
  
- <script src="http://gist-it.appspot.com/github/horstjens/ThePythonGameBook/blob/master/pygame/020_shooting_from_tank.py">​ +<code python>​ 
- </script></html>+#​!/​usr/​bin/​env python 
 +# -*- coding: utf-8 -*- 
 +"""​ 
 +020_shooting_from_tank.py 
 +demo of tank game with rotating turrets 
 +url: http://​thepythongamebook.com/​en:​part2:​pygame:​step020 
 +author: horst.jens@spielend-programmieren.at 
 +licence: gpl, see http://​www.gnu.org/​licenses/​gpl.html 
 + 
 +demo of 2 tanks shooting bullets at the end of it's cannon 
 +and shooting tracers at the end of it's bow Machine Gun 
 +and from the turret-machine gun (co-axial with main gun) 
 + 
 +works with pyhton3.4 and python2.7 
 +"""​ 
 + 
 +#the next line is only needed for python2.x and not necessary for python3.x 
 +from __future__ import print_function,​ division 
 +  
 +import pygame 
 +import random 
 +import math 
 +GRAD = math.pi / 180 # 2 * pi / 360   # math module needs Radiant instead of Grad 
 +  
 +class Config(object):​ 
 +    """​ a class to hold all game constants that may be modded by the user"""​ 
 +    fullscreen = False 
 +    width = 640 
 +    height = 480 
 +    fps = 100 
 +    xtiles = 30 # how many grid tiles for x axis 
 +    ytiles = 20 # how many grid tiles for y axis 
 +  
 +class Text(pygame.sprite.Sprite):​ 
 +    """​ a helper class to write text on the screen """​ 
 +    number = 0  
 +    book = {} 
 +    def __init__(self,​ pos, msg): 
 +        self.number = Text.number # get a unique number 
 +        Text.number += 1 # prepare number for next Textsprite 
 +        Text.book[self.number] = self # store myself into the book 
 +        pygame.sprite.Sprite.__init__(self,​ self.groups) 
 +        self.pos = [0.0,0.0] 
 +        self.pos[0] = pos[0] 
 +        self.pos[1] = pos[1] 
 +        self.msg = msg 
 +        self.changemsg(msg) 
 +  
 +    def update(self,​ seconds): ​        
 +        pass 
 +  
 +    def changemsg(self,​msg):​ 
 +        self.msg = msg 
 +        self.image = write(self.msg) 
 +        self.rect = self.image.get_rect() 
 +        self.rect.centerx = self.pos[0] 
 +        self.rect.centery = self.pos[1] 
 +  
 +class Bullet(pygame.sprite.Sprite):​ 
 +    """​ a big projectile fired by the tank's main cannon"""​ 
 +    side = 7 # small side of bullet rectangle 
 +    vel = 180 # velocity 
 +    mass = 50 
 +    maxlifetime = 10.0 # seconds 
 +    def __init__(self,​ boss): 
 +        pygame.sprite.Sprite.__init__(self,​ self.groups) # THE most important line ! 
 +        self.boss = boss 
 +        self.dx = 0 
 +        self.dy = 0 
 +        self.angle = 0 
 +        self.lifetime = 0.0 
 +        self.color = self.boss.color 
 +        self.calculate_heading() # !!!!!!!!!!!!!!!!!!! 
 +        self.dx += self.boss.dx 
 +        self.dy += self.boss.dy # add boss movement 
 +        self.pos = self.boss.pos[:​] # copy (!!!) of boss position  
 +        #self.pos = self.boss.pos ​  # uncomment this linefor fun effect 
 +        self.calculate_origin() 
 +        self.update() # to avoid ghost sprite in upper left corner,  
 +                      # force position calculation. 
 +  
 +    def calculate_heading(self):​ 
 +        """​ drawing the bullet and rotating it according to it's launcher"""​ 
 +        self.radius = Bullet.side # for collision detection 
 +        self.angle += self.boss.turretAngle 
 +        self.mass = Bullet.mass 
 +        self.vel = Bullet.vel 
 +        image = pygame.Surface((Bullet.side * 2, Bullet.side)) # rect 2 x 1 
 +        image.fill((128,​128,​128)) # fill grey 
 +        pygame.draw.rect(image,​ self.color, (0,​0,​int(Bullet.side * 1.5), Bullet.side)) # rectangle 1.5 length 
 +        pygame.draw.circle(image,​ self.color, (int(self.side *1.5) ,​self.side//​2),​ self.side//​2) #  circle 
 +        image.set_colorkey((128,​128,​128)) # grey transparent 
 +        self.image0 = image.convert_alpha() 
 +        self.image = pygame.transform.rotate(self.image0,​ self.angle) 
 +        self.rect = self.image.get_rect() 
 +        self.dx = math.cos(degrees_to_radians(self.boss.turretAngle)) * self.vel 
 +        self.dy = math.sin(degrees_to_radians(-self.boss.turretAngle)) * self.vel 
 +  
 +    def calculate_origin(self):​ 
 +        # - spawn bullet at end of turret barrel instead tank center - 
 +        # cannon is around Tank.side long, calculatet from Tank center 
 +        # later subtracted 20 pixel from this distance 
 +        # so that bullet spawns closer to tank muzzle 
 +        self.pos[0] +=  math.cos(degrees_to_radians(self.boss.turretAngle)) * (Tank.side-20) 
 +        self.pos[1] +=  math.sin(degrees_to_radians(-self.boss.turretAngle)) * (Tank.side-20) 
 +  
 +    def update(self,​ seconds=0.0):​ 
 +        # ---- kill if too old --- 
 +        self.lifetime += seconds 
 +        if self.lifetime > Bullet.maxlifetime:​ 
 +            self.kill() 
 +        # ------ calculate movement -------- 
 +        self.pos[0] += self.dx * seconds 
 +        self.pos[1] += self.dy * seconds 
 +        # ----- kill if out of screen 
 +        if self.pos[0] ​0: 
 +            self.kill() 
 +        elif self.pos[0] > Config.width:​ 
 +            self.kill() 
 +        if self.pos[1] < 0: 
 +            self.kill() 
 +        elif self.pos[1] > Config.height:​ 
 +            self.kill() 
 +        #------- move ------- 
 +        self.rect.centerx ​round(self.pos[0],​0) 
 +        self.rect.centery = round(self.pos[1],​0) 
 +  
 +class Tracer(Bullet):​ 
 +    ​"""​Tracer is nearly the same as Bullet, but smaller 
 +       and with another origin (bow MG rect instead cannon. 
 +       ​Tracer inherits all methods of Bullet, but i overwrite 
 +       ​calculate_heading and calculate_origin"""​ 
 +    side = 15 # long side of bullet rectangle 
 +    vel = 200 # velocity 
 +    mass = 10 
 +    color = (200,​0,​100) 
 +    maxlifetime = 10.0 # seconds 
 +    def __init__(self,​ boss, turret=False): 
 +        self.turret = turret 
 +        Bullet.__init__(self,​boss ) # this line is important  
 +  
 +    def calculate_heading(self):​ 
 +        """​overwriting the method because there are some differences  
 +           ​between a tracer and a main gun bullet"""​ 
 +        self.radius = Tracer.side # for collision detection 
 +        self.angle = 0 
 +        self.angle += self.boss.tankAngle 
 +        if self.turret:​ 
 +            self.angle = self.boss.turretAngle 
 +        self.mass = Tracer.mass 
 +        self.vel = Tracer.vel 
 +        image = pygame.Surface((Tracer.side,​ Tracer.side ​4)) # a line  
 +        image.fill(self.boss.color) # fill yellow ?  
 +        pygame.draw.rect(image,​ (0,0,0), (Tracer.side * .75, 0, Tracer.side,​ Tracer.side ​4)) # red dot at front 
 +        image.set_colorkey((128,​128,​128)) # grey transparent 
 +        self.image0 = image.convert_alpha() 
 +        self.image = pygame.transform.rotate(self.image0,​ self.angle) 
 +        self.rect = self.image.get_rect() 
 +        if self.turret:​ 
 +            # turret mg 
 +            self.dx = math.cos(degrees_to_radians(self.boss.turretAngle)) * self.vel 
 +            self.dy = math.sin(degrees_to_radians(-self.boss.turretAngle)) * self.vel 
 +        else: 
 +            # bow mg 
 +            self.dx = math.cos(degrees_to_radians(self.boss.tankAngle)) * self.vel 
 +            self.dy = math.sin(degrees_to_radians(-self.boss.tankAngle)) * self.vel 
 +  
 +    def calculate_origin(self):​ 
 +        """​overwriting because another point of origin is needed"""​ 
 +        # - spawn bullet at end of machine gun muzzle (bow or turret) 
 +        if self.turret:​ 
 +            self.pos[0] +=  math.cos(degrees_to_radians(-90+self.boss.turretAngle)) * 15 
 +            self.pos[1] +=  math.sin(degrees_to_radians(90-self.boss.turretAngle)) * 15 
 +        else: 
 +            self.pos[0] +=  math.cos(degrees_to_radians(30+self.boss.tankAngle)) * (Tank.side/​2) 
 +            self.pos[1] +=  math.sin(degrees_to_radians(-30-self.boss.tankAngle)) * (Tank.side/​2) 
 +  
 +class Tank(pygame.sprite.Sprite):​ 
 +    """​ A Tank, controlled by the Player with Keyboard commands. 
 +    This Tank draw it's own Turret (including the main gun)  
 +    and it's bow rectangle (slit for Tracer Machine Gun"""​ 
 +    side = 100 # side of the quadratic tank sprite 
 +    recoiltime = 0.75 # how many seconds ​ the cannon is busy after firing one time 
 +    mgrecoiltime = 0.2 # how many seconds the bow mg (machine gun) is idle 
 +    turretTurnSpeed = 25 # turret 
 +    tankTurnSpeed = 8 # tank 
 +    movespeed = 25 
 +    maxrotate = 360 # maximum amount of degree the turret is allowed to rotate 
 +    book = {} # a book of tanks to store all tanks 
 +    number = 0 # each tank gets his own number 
 +    # keys for tank control, expand if you need more tanks 
 +    #          player1, ​       player2 ​   etc 
 +    firekey = (pygame.K_k,​ pygame.K_DOWN) 
 +    mgfirekey = (pygame.K_LCTRL,​ pygame.K_KP_ENTER) 
 +    mg2firekey = (pygame.K_i,​ pygame.K_UP) 
 +    turretLeftkey = (pygame.K_j,​ pygame.K_LEFT) 
 +    turretRightkey = (pygame.K_l,​ pygame.K_RIGHT) 
 +    forwardkey = (pygame.K_w,​ pygame.K_KP8) 
 +    backwardkey = (pygame.K_s,​ pygame.K_KP5) 
 +    tankLeftkey = (pygame.K_a,​ pygame.K_KP4) 
 +    tankRightkey = (pygame.K_d,​ pygame.K_KP6) 
 +    color = ((200,​200,​0),​ (0,​0,​200)) 
 +    msg = ["wasd LCTRL, ijkl", "​Keypad:​ 4852, ENTER, cursor"​] 
 +  
 +    def __init__(self,​ startpos = (150,150), angle=0): 
 +        self.number = Tank.number # now i have a unique tank number 
 +        Tank.number += 1 # prepare number for next tank 
 +        Tank.book[self.number] = self # store myself into the tank book 
 +        pygame.sprite.Sprite.__init__(self,​ self.groups) # THE most important line ! 
 +        self.pos = [startpos[0],​ startpos[1]] # x,y 
 +        self.dx = 0 
 +        self.dy = 0 
 +        self.ammo = 30 # main gun 
 +        self.mgammo = 500 # machinge gun 
 +        self.msg =  "​player%i:​ ammo: %i/%i keys: %s" % (self.number+1,​ self.ammo, self.mgammo,​ Tank.msg[self.number]) 
 +        Text((Config.width/2, 30+20*self.number),​ self.msg) # create status line text sprite 
 +        self.color = Tank.color[self.number] 
 +        self.turretAngle = angle #turret facing 
 +        self.tankAngle = angle # tank facing 
 +        self.firekey = Tank.firekey[self.number] # main gun 
 +        self.mgfirekey = Tank.mgfirekey[self.number] # bow mg 
 +        self.mg2firekey = Tank.mg2firekey[self.number] # turret mg 
 +        self.turretLeftkey = Tank.turretLeftkey[self.number] # turret 
 +        self.turretRightkey = Tank.turretRightkey[self.number] # turret 
 +        self.forwardkey = Tank.forwardkey[self.number] # move tank 
 +        self.backwardkey = Tank.backwardkey[self.number] # reverse tank 
 +        self.tankLeftkey = Tank.tankLeftkey[self.number] # rotate tank 
 +        self.tankRightkey = Tank.tankRightkey[self.number] # rotat tank 
 +        # painting facing north, have to rotate 90° later 
 +        image = pygame.Surface((Tank.side,​Tank.side)) # created on the fly 
 +        image.fill((128,​128,​128)) # fill grey 
 +        if self.side > 10: 
 +             ​pygame.draw.rect(image,​ self.color, (5,​5,​self.side-10,​ self.side-10)) #tank body, margin 5 
 +             ​pygame.draw.rect(image,​ (90,90,90), (0,​0,​self.side//6, self.side)) # track left 
 +             ​pygame.draw.rect(image,​ (90,90,90), (self.side-self.side//6, 0, self.side,​self.side)) # right track 
 +             pygame.draw.rect(image,​ (255,0,0), (self.side//6+5 , 10, 10, 5)) # red bow rect left 
 +             #​pygame.draw.rect(image,​ (255,0,0), (self.side/​2 - 5, 10, 10, 5)) # red bow rect middle 
 +        pygame.draw.circle(image,​ (255,0,0), (self.side//​2,​self.side//​2),​ self.side//​3 , 2) # red circle for turret 
 +        image = pygame.transform.rotate(image,​-90) # rotate so to look east 
 +        self.image0 = image.convert_alpha() 
 +        self.image = image.convert_alpha() 
 +        self.rect = self.image0.get_rect() 
 +        #---------- turret ------------------ 
 +        self.firestatus = 0.0 # time left until cannon can fire again 
 +        self.mgfirestatus = 0.0 # time until mg can fire again 
 +        self.mg2firestatus = 0.0 # time until turret mg can fire again 
 +        self.turndirection = 0    # for turret 
 +        self.tankturndirection = 0 
 +        self.movespeed = Tank.movespeed 
 +        self.turretTurnSpeed = Tank.turretTurnSpeed 
 +        self.tankTurnSpeed = Tank.tankTurnSpeed 
 +        Turret(self) # create a Turret for this tank 
 +  
 +    def update(self,​ seconds): 
 +        # no need for seconds but the other sprites need it 
 +        #-------- reloading, firestatus---------- 
 +        if self.firestatus > 0: 
 +            self.firestatus -= seconds # cannon will soon be ready again 
 +            if self.firestatus <0: 
 +                self.firestatus = 0 #avoid negative numbers 
 +        if self.mgfirestatus > 0: 
 +            self.mgfirestatus -= seconds # bow mg will soon be ready again 
 +            if self.mgfirestatus <0: 
 +                self.mgfirestatus = 0 #avoid negative numbers 
 +        if self.mg2firestatus > 0: 
 +            self.mg2firestatus -= seconds # turret mg will soon be ready again 
 +            if self.mg2firestatus <0: 
 +                self.mg2firestatus = 0 #avoid negative numbers 
 +  
 +        # ------------ keyboard -------------- 
 +        pressedkeys = pygame.key.get_pressed() 
 +        # -------- turret manual rotate ---------- 
 +        self.turndirection = 0    #  left / right turret rotation 
 +        if pressedkeys[self.turretLeftkey]:​ 
 +            self.turndirection += 1 
 +        if pressedkeys[self.turretRightkey]:​ 
 +            self.turndirection -= 1 
 +  
 +        #---------- tank rotation --------- 
 +        self.tankturndirection = 0 # reset left/right rotation 
 +        if pressedkeys[self.tankLeftkey]:​ 
 +            self.tankturndirection += 1 
 +        if pressedkeys[self.tankRightkey]:​ 
 +            self.tankturndirection -= 1 
 +  
 +        # ---------------- rotate tank --------------- 
 +        self.tankAngle += self.tankturndirection * self.tankTurnSpeed * seconds # time-based turning of tank 
 +        # angle etc from Tank (boss) 
 +        oldcenter = self.rect.center 
 +        oldrect = self.image.get_rect() # store current surface rect 
 +        self.image ​ = pygame.transform.rotate(self.image0,​ self.tankAngle)  
 +        self.rect = self.image.get_rect() 
 +        self.rect.center = oldcenter  
 +        # if tank is rotating, turret is also rotating with tank ! 
 +        # -------- turret autorotate ---------- 
 +        self.turretAngle += self.tankturndirection * self.tankTurnSpeed * seconds ​ + self.turndirection * self.turretTurnSpeed * seconds # time-based turning 
 +        # ---------- fire cannon ----------- 
 +        if (self.firestatus ==0) and (self.ammo > 0): 
 +            if pressedkeys[self.firekey]:​ 
 +                self.firestatus = Tank.recoiltime # seconds until tank can fire again 
 +                Bullet(self) ​    
 +                self.ammo -= 1 
 +                self.msg =  ​"player%i: ammo: %i/%i keys: %s" % (self.number+1,​ self.ammo, self.mgammo,​ Tank.msg[self.number]) 
 +                Text.book[self.number].changemsg(self.msg) 
 +        # -------- fire bow mg --------------- 
 +        if (self.mgfirestatus ==0) and (self.mgammo ​>0): 
 +            if pressedkeys[self.mgfirekey]:​ 
 +                self.mgfirestatus = Tank.mgrecoiltime 
 +                Tracer(self,​ False) # turret mg = False 
 +                self.mgammo -= 1 
 +                self.msg = "​player%i:​ ammo: %i/%i keys: %s" % (self.number+1,​ self.ammo, self.mgammo,​ Tank.msg[self.number]) 
 +                Text.book[self.number].changemsg(self.msg) 
 +        # -------- fire turret mg --------------- 
 +        if (self.mg2firestatus ==0) and (self.mgammo >0): 
 +            if pressedkeys[self.mg2firekey]:​ 
 +                self.mg2firestatus = Tank.mgrecoiltime # same recoiltime for both mg's 
 +                Tracer(self,​ True) # turret mg = True 
 +                self.mgammo -= 1 
 +                self.msg =  "​player%i:​ ammo: %i/%i keys: %s" % (self.number+1,​ self.ammo, self.mgammo,​ Tank.msg[self.number]) 
 +                Text.book[self.number].changemsg(self.msg) 
 +        # ---------- movement ------------ 
 +        self.dx = 0 
 +        self.dy = 0 
 +        self.forward = 0 # movement calculator 
 +        if pressedkeys[self.forwardkey]:​ 
 +            self.forward += 1 
 +        if pressedkeys[self.backwardkey]:​ 
 +            self.forward -= 1 
 +        # if both are pressed togehter, self.forward becomes 0 
 +        if self.forward == 1: 
 +            self.dx =  math.cos(degrees_to_radians(self.tankAngle)) * self.movespeed 
 +            self.dy =  -math.sin(degrees_to_radians(self.tankAngle)) * self.movespeed 
 +        if self.forward == -1: 
 +            self.dx =  -math.cos(degrees_to_radians(self.tankAngle)) * self.movespeed 
 +            self.dy =  math.sin(degrees_to_radians(self.tankAngle)) * self.movespeed 
 +        # ------------- check border collision --------------------- 
 +        self.pos[0] += self.dx * seconds 
 +        self.pos[1] += self.dy * seconds 
 +        if self.pos[1] + self.side//​2 >= Config.height:​ 
 +            self.pos[1] = Config.height - self.side//​2 
 +            self.dy = 0 # crash into border 
 +        elif self.pos[1] -self.side/​2 ​<= 0: 
 +            self.pos[1] = 0 + self.side//2 
 +            self.dy = 0 
 +        # ---------- paint sprite at correct position --------- 
 +        self.rect.centerx = round(self.pos[0],​ 0) #x 
 +        self.rect.centery = round(self.pos[1],​ 0) #y     
 +  
 +class Turret(pygame.sprite.Sprite):​ 
 +    """​turret on top of tank"""​ 
 +    def __init__(self,​ boss): 
 +        pygame.sprite.Sprite.__init__(self,​ self.groups) # THE most important line ! 
 +        self.boss = boss 
 +        self.side = self.boss.side ​        
 +        self.images = {} # how much recoil after shooting, reverse order of apperance 
 +        self.images[0] = self.draw_cannon(0) ​ # idle position 
 +        self.images[1] = self.draw_cannon(1) 
 +        self.images[2] = self.draw_cannon(2) 
 +        self.images[3] = self.draw_cannon(3) 
 +        self.images[4] = self.draw_cannon(4) 
 +        self.images[5] = self.draw_cannon(5) 
 +        self.images[6] = self.draw_cannon(6) 
 +        self.images[7] = self.draw_cannon(7) 
 +        self.images[8] = self.draw_cannon(8) ​ # position of max recoil 
 +        self.images[9] = self.draw_cannon(4) 
 +        self.images[10] = self.draw_cannon(0) # idle position 
 +  
 +    def update(self,​ seconds): ​        
 +        # painting the correct image of cannon 
 +        if self.boss.firestatus ​0: 
 +            self.image = self.images[int(self.boss.firestatus // (Tank.recoiltime / 10.0))] 
 +        else: 
 +            self.image = self.images[0] 
 +        # --------- rotating ------------- 
 +        # angle etc from Tank (boss) 
 +        oldrect = self.image.get_rect() # store current surface rect 
 +        self.image ​ = pygame.transform.rotate(self.image,​ self.boss.turretAngle)  
 +        self.rect = self.image.get_rect() 
 +        # ---------- move with boss --------- 
 +        self.rect = self.image.get_rect() 
 +        self.rect.center = self.boss.rect.center 
 +  
 +    def draw_cannon(self,​ offset): 
 +         # painting facing right, offset is the recoil 
 +         image = pygame.Surface((self.boss.side * 2,​self.boss.side * 2)) # created on the fly 
 +         ​image.fill((128,​128,​128)) # fill grey 
 +         ​pygame.draw.circle(image,​ (255,0,0), (self.side,​self.side),​ 22, 0) # red circle 
 +         ​pygame.draw.circle(image,​ (0,255,0), (self.side,​self.side),​ 18, 0) # green circle 
 +         ​pygame.draw.rect(image,​ (255,0,0), (self.side-10,​ self.side + 10, 15,2)) # turret mg rectangle 
 +         ​pygame.draw.rect(image,​ (0,255,0), (self.side-20 - offset,​self.side - 5, self.side - offset,10)) # green cannon 
 +         ​pygame.draw.rect(image,​ (255,0,0), (self.side-20 - offset,​self.side - 5, self.side - offset,​10),​1) # red rect  
 +         ​image.set_colorkey((128,​128,​128)) 
 +         ​return image 
 +# ---------------- End of classes -------------------- 
 +#​------------ defs ------------------ 
 +def radians_to_degrees(radians):​ 
 +    return (radians / math.pi) * 180.0 
 +  
 +def degrees_to_radians(degrees):​ 
 +    return degrees * (math.pi / 180.0) 
 +  
 +def write(msg="​pygame is cool"​):​ 
 +    """​helper function for the Text sprite"""​ 
 +    myfont = pygame.font.SysFont("​None",​ 28) 
 +    mytext = myfont.render(msg,​ True, (255,​0,​0)) 
 +    mytext = mytext.convert_alpha() 
 +    return mytext ​        
 +  
 +def pressedKeysString():​ 
 +    """​returns the pressed keys (for the player1 tank) to be displayd in the status line"""​ 
 +    pressedkeys = pygame.key.get_pressed() 
 +    line = ""​ 
 +    if pressedkeys[pygame.K_a]:​ 
 +        line += "a " 
 +    if pressedkeys[pygame.K_d]:​ 
 +        line += "d " 
 +    if pressedkeys[pygame.K_w]:​ 
 +        line += "w " 
 +    if pressedkeys[pygame.K_s]:​ 
 +        line += "s " 
 +    if pressedkeys[pygame.K_LCTRL]:​ 
 +        line += "​LCTRL"​ 
 +    return line 
 +  
 +def main(): 
 +    """​the game itself"""​ 
 +    pygame.init() 
 +    screen=pygame.display.set_mode((Config.width,​Config.height))  
 +    background = pygame.Surface((screen.get_size())) 
 +    background.fill((128,​128,​255)) # fill grey light blue:​(128,​128,​255)  
 +    # paint a grid of white lines 
 +    for x in range(0,​Config.width,​Config.width//​Config.xtiles):​ #start, stop, step 
 +        pygame.draw.line(background,​ (255,​255,​255),​ (x,0), (x,​Config.height)) 
 +    for y in range(0,​Config.height,​Config.height//​Config.ytiles):​ #start, stop, step 
 +        pygame.draw.line(background,​ (255,​255,​255),​ (0,y), (Config.width,​y)) 
 +    # paint upper rectangle to have background for text 
 +    pygame.draw.rect(background,​ (128,​128,​255),​ (0,​0,​Config.width,​ 70)) 
 +  
 +    background = background.convert() 
 +    screen.blit(background,​ (0,0)) # delete all 
 +    clock = pygame.time.Clock() ​   # create pygame clock object 
 +    FPS = Config.fps ​              # desired max. framerate  
 +    playtime = 0 
 +  
 +    tankgroup = pygame.sprite.Group() 
 +    bulletgroup = pygame.sprite.Group() 
 +    allgroup = pygame.sprite.LayeredUpdates() 
 +  
 +    Tank._layer = 4   # base layer 
 +    Bullet._layer = 7 # to prove that Bullet is in top-layer 
 +    Tracer._layer = 5 # above Tank, but below Turret 
 +    Turret._layer = 6 # above Tank & Tracer 
 +    Text._layer = 3   # below Tank 
 +  
 +    #assign default groups to each sprite class 
 +    Tank.groups = tankgroup, allgroup 
 +    Turret.groups = allgroup 
 +    Bullet.groups = bulletgroup,​ allgroup 
 +    Text.groups = allgroup 
 +    player1 = Tank((150,​250),​ 90) # create ​ first tank, looking north 
 +    player2 = Tank((450,​250),​ -90) # create second tank, looking south 
 +    status3 = Text((Config.width//​2,​ 10), "Tank Demo. Press ESC to quit"​) 
 +    mainloop = True            
 +    while mainloop: 
 +        milliseconds = clock.tick(Config.fps) ​ # milliseconds passed since last frame 
 +        seconds = milliseconds / 1000.0 # seconds passed since last frame (float) 
 +        playtime += seconds 
 +  
 +        for event in pygame.event.get():​ 
 +            if event.type == pygame.QUIT:​ 
 +                # pygame window closed by user 
 +                mainloop = False  
 +            elif event.type == pygame.KEYDOWN:​ 
 +                if event.key == pygame.K_ESCAPE:​ 
 +                    mainloop = False # exit game 
 +  
 +        pygame.display.set_caption("​FPS:​ %.2f keys: %s" % ( clock.get_fps(),​ pressedKeysString())) 
 +        #​screen.blit(background,​ (0,0)) # delete all 
 +        allgroup.clear(screen,​ background) # funny effect if you outcomment this line 
 +        allgroup.update(seconds) 
 +        allgroup.draw(screen) 
 +        pygame.display.flip() # flip the screen 30 times a second 
 +    return 0 
 +  
 +if __name__ == '​__main__':​ 
 +    main() 
 + 
 +</code>
  
 ^ [[:​en:​pygame:​step019| ← previous]] ^ [[en:​pygame:​start| ↑ Overview]] ^ [[:​en:​pygame:​step021| → next ]] ^ ^ [[:​en:​pygame:​step019| ← previous]] ^ [[en:​pygame:​start| ↑ Overview]] ^ [[:​en:​pygame:​step021| → next ]] ^
  
-====== comment this page ====== 
-~~DISQUS~~ 
  
/var/www/horst/thepythongamebook.com/data/pages/en/pygame/step020.txt · Last modified: 2020/05/15 22:53 by Horst JENS