2015-05-24 6 views
0

Я пишу игру с pygame, которая включает в себя два контролируемых игроками танков, которые идут вокруг кирпичной карты со своими собственными барами здоровья и стреляют друг в друга с помощью одной пули. Из того, что я могу сказать, все остальное работает, но у меня возникают проблемы с определением поверхности, на которой можно нарисовать кирпичи, резервуары и пули: «фон» или «экран» (кирпичи не меняются во время игры, только танков и пуль). Я пробовал рисовать все, кроме баров здоровья на заднем плане, но это только привело к появлению черного экрана, на котором отображались только бары здоровья. Затем я вытащил все прямо на экран и сначала отображает все правильно, но когда танки перемещаются, экран не обновляется (я получаю много изображений танков, перекрывающих друг друга, когда танк перемещается), и пули не срабатывают в результате. Код ниже, но метод main() находится в самом низу, и именно это вызывает ошибки. Файл «effects.py», который импортируется на самом верху, содержит только классы «стрелы» и «бомбы», которые являются только специальными эффектами, но до сих пор не используются в методе main(), поэтому их можно игнорировать ,Рисование изображений на фоне или экране Пигама

from __future__ import print_function, division 

import pygame, os, sys 
from pygame.locals import * 
import random 
import effects 
from effects import * 
import math 
GRAD = math.pi/180 

class Brick(pygame.sprite.Sprite): 

    def __init__(self, pos, image, top, bottom, right, left, bricks): 

     pygame.sprite.Sprite.__init__(self) 

     self.rect = image.get_rect(topleft = pos) 
     self.image = image 
     self.pos = pos 
     self.top = top 
     self.bottom = bottom 
     self.right = right 
     self.left = left 
     self.health = 30 
     bricks.add(self) 


class City(object): 

    def __init__(self, bricks, level): 

     self.level = level 

     self.city = self.level.convert_alpha() 

     self.brick = pygame.image.load("brick.png").convert_alpha() 
     self.bricks = bricks 

     self.x = self.y = 0 
     collidable = (255, 0, 0, 255) 
     self.height = self.city.get_height() 
     self.width = self.city.get_width() 
     self.vehicle_pos = (0,0) 

     while self.y < self.height: 
      color = self.city.get_at((self.x, self.y)) 
      collidable = (255, 0, 0, 255), (0,0,0,255) 
      top = False 
      bottom = False 
      right = False 
      left = False 
      if color in collidable: 
       self.bricks.add(Brick((self.x*30, self.y*30), self.brick, top, bottom, right, left, self.bricks)) 
       print ("brick added!") 
       print (self.x, self.y) 


      self.x += 1 

      if self.x >= self.width: 
       self.x = 0 
       self.y += 1 

    def get_size(self): 
     return [self.city.get_size()[0]*30, self.city.get_size()[1]*30] 


class Tank(pygame.sprite.Sprite): 

    book = {} # a book of tanks to store all tanks 
    number = 0 # each tank gets his own number 

    firekey = (pygame.K_SPACE, pygame.K_RETURN) 
    forwardkey = (pygame.K_w, pygame.K_i) 
    backwardkey = (pygame.K_s, pygame.K_k) 
    tankLeftkey = (pygame.K_a, pygame.K_j) 
    tankRightkey = (pygame.K_d, pygame.K_l) 

    color = ((200,200,0), (0,0,200)) 

    def __init__(self, pos, angle, health): 
     self.number = Tank.number 
     Tank.number += 1 
     Tank.book[self.number] = self 
     pygame.sprite.Sprite.__init__(self) 
     self.tank_pic = pygame.image.load("tank.png").convert_alpha() 
     self.image = self.tank_pic 
     self.image_type = self.tank_pic 
     self.tank1_pic = pygame.image.load("tank1.png").convert_alpha() 
     self._image = self.image 
     self.rect = self.image.get_rect() 
     self.rect = self.rect.move(pos) 
     self.tankAngle = angle # tank facing 

     #---handles controls---# 

     self.firekey = Tank.firekey[self.number] # main gun 
     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 


     self.health = health 
     self.alive = True 
     self.speed = 5 
     self.angle = angle 
     self.timer = 3 
     self.timerstart = 0 
     self.x, self.y = self.rect.center 
     self.bullet_s = pygame.mixer.Sound("bullet.wav") 
     self.bullet_s.set_volume(.25) 

    def rotate(self): 
     center = self.rect.center 
     self.image = pygame.transform.rotozoom(self._image, self.angle, 1.0) 
     self.rect = self.image.get_rect(center = center) 

    def update(self, keys, bricks, bullets, booms, bombs): 
     self.bricks = bricks 
     self.t = True 
     self._rect = Rect(self.rect) 
     self._rect.center = self.x, self.y 
     self.rotate() 
     turn_speed = 3 


     pressedkeys = pygame.key.get_pressed() 

     if pressedkeys[self.forwardkey]: 
      self.x += sin(radians(self.angle))*-self.speed 
      self.y += cos(radians(self.angle))*-self.speed 
     if pressedkeys[self.backwardkey]: 
      self.x += sin(radians(self.angle))*self.speed 
      self.y += cos(radians(self.angle))*self.speed 
     if pressedkeys[self.tankLeftkey]: 
      self.angle += turn_speed 
     if pressedkeys[self.tankRightkey]: 
      self.angle -= turn_speed 
     if keys[self.firekey]: 
      if self.timer >= 3: 
       self.timer = self.timerstart 
       self.b_size = "small" 
       bullets.add(Bullet(self.rect.center, self.angle, self.b_size, "vehicle")) 
       self.bullet_s.play() 

     if self.timer < 3: 
      self.timer += 1 

     if self.angle > 360: 
      self.angle = self.angle-360 
     if self.angle <0: 
      self.angle = self.angle+360 

     self.rect.center = self.x, self.y 

     x = self.rect.centerx 
     y = self.rect.centery 
     _x = self._rect.centerx 
     _y = self._rect.centery 
     for b in bricks: 
      if self.rect.colliderect(b.rect): 
       if _x+21 <= b.rect.left and x+21 > b.rect.left: 
        if b.left == True: 
         self.x = b.rect.left-21 
       if _x-21 >= b.rect.right and x-21 < b.rect.right: 
        if b.right == True: 
         self.x = b.rect.right+21 
       if _y+21 <= b.rect.top and y+21 > b.rect.top: 
        if b.top == True: 
         self.y = b.rect.top-21 
       if _y-21 >= b.rect.bottom and y-21 < b.rect.bottom: 
        if b.bottom == True: 
         self.y = b.rect.bottom+21 

     for b in bullets: 
      if self.rect.colliderect(b.rect): 
       b_size = b.get_size() 
       pygame.sprite.Sprite.kill(b) 
       if b_size == "small": 
        booms.add(Boom(b.rect.center, "small")) 
        self.health -= 1 
       if b_size == "big": 
        booms.add(Boom(b.rect.center, "big")) 
        self.health -=5 

     for b in bombs: 
      if self.rect.colliderect(b.rect) and b.timer == 20: 
       self.health -=5 

     if self.health <= 0: 
      booms.add(Boom(self.rect.center, "huge")) 
      self.alive = False 
      self.health = 0 
     '''if self.image_type == self.tank_pic: 
      self.image = self.tank1_pic 
      self.image_type = self.tank1_pic 
      print "switch 1" 
     if self.image_type == self.tank1_pic: 
      self.image = self.tank_pic 
      self.image_type = self.tank_pic 
      print "switch 2"''' 

class Turret(pygame.sprite.Sprite): 

    def __init__(self, pos, angle, follow): 
     pygame.sprite.Sprite.__init__(self) 
     self.image = pygame.image.load("turret.png").convert_alpha() 
     self.timer = 40 
     self.timer_start = self.timer 
     self.size = "big" 
     self.bang_s = pygame.mixer.Sound("bang.wav") 
     self.speed = 3 
     self.bang_s.set_volume(1.0) 
     self._image = self.image 
     self.rect = self.image.get_rect() 
     self.rect = self.rect.move(pos) 
     self.angle = angle 
     self.timer = 40 
     self.wait_timer = 5 
     self.timer_restart = 0 
     self.x, self.y = self.rect.center 
     self.follow = follow 

    def rotate(self): 
     center = self._rect.center 
     self.image = pygame.transform.rotozoom(self._image, self.angle, 1.0) 
     self.rect = self.image.get_rect(center = center) 

    def update(self, pos, mx, my, keys, booms, tank_angle, bricks, background, city): 
     self.background = background 
     self.city_size = city 
     self.t = True 
     self.bricks = bricks 
     self.end = None 
     self._rect = Rect(self.rect) 
     self._rect.center = pos 
     self.tank_angle = tank_angle 
     t_x, t_y = self.rect.center 


     if keys[K_m]: 
      if self.wait_timer >= 5: 
       self.follow = not self.follow 
       self.wait_timer = self.timer_restart 
     if self.follow: 
      self.mouse_angle = math.atan2(xd, yd)*(180/math.pi)+180 #used atan2(x,y) instead of atan2(y,x). Sprite was origanly drawn along the y axis, gave better results 
      if self.angle < self.mouse_angle: 
       if math.fabs(self.angle - self.mouse_angle) < 180: 
        self.angle +=self.speed 
       else: 
        self.angle -=self.speed 
      else: 
       if math.fabs(self.angle - self.mouse_angle) < 180: 
        self.angle -=self.speed 
       else: 
        self.angle +=self.speed 
      if math.fabs(self.angle - self.mouse_angle) < self.speed+.5: 
       self.angle = self.mouse_angle 

     if not self.follow: 
      if self.angle != self.tank_angle: 
       if self.angle < self.tank_angle: 
        if math.fabs(self.angle - self.tank_angle) < 180: 
         self.angle +=self.speed 
        else: 
         self.angle -=self.speed 
       else: 
        if math.fabs(self.angle - self.tank_angle) < 180: 
         self.angle -=self.speed 
        else: 
         self.angle +=self.speed 
       if math.fabs(self.angle - self.tank_angle) < self.speed+.5: 
        self.angle = self.tank_angle 
      else: 
       self.angle = self.tank_angle 

     self.rotate() 
     if self.angle > 360: 
      self.angle = self.angle-360 
     if self.angle <0: 
      self.angle = self.angle+360 
     if self.wait_timer < 5: 
      self.wait_timer += 1 



# ---------- END OF CLASSES ---------- # 


def main(): 

    pygame.init() 
    version = "Tank Wars 2.0" 
    screen = pygame.display.set_mode((1170, 510),0,32) 
    n = 1 
    size = screen.get_size() 
    pygame.mouse.set_visible(False) 
    map_ = pygame.image.load("c2.png") 
    health = 40 
    health_full = health 

    bricks= pygame.sprite.Group() 
    bricks_des = pygame.sprite.Group() 
    bricks_non = pygame.sprite.Group() 
    bullets = pygame.sprite.Group() 
    booms = pygame.sprite.Group() 
    bombers = pygame.sprite.Group() 
    bombs = pygame.sprite.Group() 
    tanks = pygame.sprite.Group() 
    allgroup = pygame.sprite.LayeredUpdates() 


    #assign default groups to each sprite class 
    #Tank.groups = tanks, allgroup 
    #Turret.groups = allgroup 
    #Bullet.groups = bullets, allgroup 

    city = City(bricks, map_) 
    city_size = city.get_size() 
    clock = pygame.time.Clock() 
    timer = 0 
    chance = None 
    score = 0 

    player1 = Tank((150, 250), 360, 40) 
    tanks.add(player1) 
    player2 = Tank((1100, 250), 360, 40) 
    tanks.add(player2) 
    player1_turret = Turret((150, 250), 360, False) 
    player2_turret = Turret((1100, 250), 360, False) 


    background = pygame.Surface((city_size), 0, 32) 
    city.bricks.draw(screen) 


    font4 = pygame.font.Font("7theb.ttf", 13) 
    font5 = pygame.font.SysFont("Courier New", 16, bold=True) 


    while True: 
     for event in pygame.event.get(): 
      if event.type == QUIT: 
       pygame.quit() 
       sys.exit() 
      if event.type == KEYDOWN: 
       if event.key == K_ESCAPE: 
        return 

     clock.tick(24) 
     time_passed = clock.tick() 
     keys = pygame.key.get_pressed() 
     m_x, m_y = pygame.mouse.get_pos() 

     background.fill((87, 87, 87)) 

     if player1.alive == True: 
      player1.update(keys, bricks, bullets, booms, bombs) 
      player1_turret.update(player1.rect.center, m_x, m_y, keys, booms, 360, bricks, background, city_size) 
      screen.blit(player1.image, player1.rect) 
      screen.blit(player1_turret.image, player1_turret.rect) 
     if player2.alive == True: 
      player2.update(keys, bricks, bullets, booms, bombs) 
      player2_turret.update(player2.rect.center, m_x, m_y, keys, booms, 360, bricks, background, city_size) 
      screen.blit(player2.image, player2.rect) 
      screen.blit(player2_turret.image, player2_turret.rect) 

     bullets.update(bricks, booms) 
     bombs.update(booms, player1) 
     bombs.update(booms, player2) 
     booms.update(background) 


     bombs.draw(screen) 
     bullets.draw(screen) 
     bombers.draw(screen) 


     healthshow = font4.render('Health ', False, (255,255,255)) 

     #---Player 1 Healthbar---# 

     pygame.draw.ellipse(screen, (255, ((player1.health*255)/health_full),0), (90, 20, 10, 13)) 
     pygame.draw.ellipse(screen, (255, ((player1.health*255)/health_full),0), (92+(100*(float(player1.health)/float(health_full))), 20, 10, 13)) 
     screen.fill((255,((player1.health*255)/health_full),0),(96,20,(100*(float(player1.health)/float(health_full))), 13)) 
     screen.blit(healthshow, (5, 20)) 

     #---Player 2 Healthbar---# 

     pygame.draw.ellipse(screen, (255, ((player2.health*255)/health_full),0), (90, 20, 10, 13)) 
     pygame.draw.ellipse(screen, (255, ((player2.health*255)/health_full),0), (92+(100*(float(player2.health)/float(health_full))), 20, 10, 13)) 
     screen.fill((255,((player2.health*255)/health_full),0),(96,20,(100*(float(player2.health)/float(health_full))), 13)) 
     screen.blit(healthshow, (500, 20)) 


     allgroup.clear(screen, background) 
     pygame.display.flip() 


if __name__ == "__main__": 

    main() 
+0

Это означает, что вы либо не обновляете танк, который был нарисован в последнем кадре, либо что по какой-то причине вы рисуете все резервуары вместе. Как первая проблема, вероятно, проблема, после щелчка на дисплее попробуйте «pygame.display.update (tank.rect)», где «tank» - это класс резервуара, изображения которого перекрываются. Кстати, обратите внимание, что при возникновении проблемы вы всегда можете импортировать отладчик ('gdb'). –

+0

рисую танки по отдельности, как это для каждого игрока: screen.blit (player1.image, player1.rect) screen.blit (player1_turret.image, player1_turret.rect) Я пытался делать то, что вы предложили, но Бесполезный «Исправить проблему сотен изображений танков, которые рисуются и не обновляться. Есть ли еще одна проблема? Кроме того, когда я пытаюсь: import gdb не работает - мне что-то нужно скачать? Благодарю. – Billybobob123

ответ

0

Мое предложение сделать глобальную screen переменную (вместо того, чтобы быть обернуты внутри функции, и создать единый имидж города, с кирпичами, добавленных к нему. Так как те все компоненты, которые не меняются, это может быть выведено на экран каждый раз, когда кадр обновляется.

После этого, на каждый кадре, бак (с баром здоровья и другими вещами) и пули могут быть выведены непосредственно к переменным screen.

Вероятно, проще всего сделать pygame.display.flip() после того, как все b litting делается, но сохраняющий массив pygame.Rects представляющих Blit позиции и затем сохраняя старую Blit Rects, а затем сделать что-то вроде:

old_rects = current_rects 
current_rects = [] 
#make blits, collect Rects in current_rects 
pygame.display.update(current_rects + old_rects) 

Таким образом, pygame.display.update() может использоваться (так как он более эффективен), и не будет проблем без освежения.

Надеюсь, это сработает и вы сможете реализовать что-то подобное.

Смежные вопросы