Related
I am trying to move a rectangle over the waves,trying to simulate a boat sailing.
For that, I rotate the rectangle using the height of the drawn lines and calculating the angle they form with the rectangle.
However, for some reason, in some points of the waves the rectangle is flickering.
The code shows the problem.
import sys
import math
import pygame
from pygame.locals import *
pygame.init()
SCREEN_WIDTH = 900
SCREEN_HEIGHT = 900
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
clock = pygame.time.Clock()
BLUE = (0, 103, 247)
RED = (255,0,0)
watter_levels = [0 for _ in range(SCREEN_WIDTH)]
def draw_water(surface, dy):
amplitude = 35
global watter_levels
for x in range(SCREEN_WIDTH):
y = int(math.sin((x)*(0.01)) * amplitude + dy)
watter_levels[x] = y
pygame.draw.aaline(surface,BLUE,(x,y),(x,y))
def get_water_level(index):
if index <= 0:
return watter_levels[0]
if index >= SCREEN_WIDTH:
return watter_levels[-1]
return watter_levels[index]
font = pygame.font.Font(None,30)
def debug(info,x=10,y=10):
display_surf = pygame.display.get_surface()
debug_surface = font.render(str(info),True,'White')
debug_rect = debug_surface.get_rect(topleft=(x,y))
pygame.draw.rect(display_surf,'Black',debug_rect)
display_surf.blit(debug_surface,debug_rect)
class Ship(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
self.image = pygame.Surface((80,80),pygame.SRCALPHA)
self.image.fill('red')
self.rect = self.image.get_rect(topleft=(0,0))
self.copy_img = self.image.copy()
self.move = pygame.math.Vector2(0,0)
self.copy_img = self.image.copy()
self.velocity = 8
def rotate(self, angle):
self.image = pygame.transform.rotate(self.copy_img, int(angle))
self.rect = self.image.get_rect(center=(self.rect.center))
def update(self):
self.get_input()
self.rect.bottom = get_water_level(self.rect.centerx)
left_y = get_water_level(self.rect.left)
right_y = get_water_level(self.rect.right)
angle = 180*math.atan2(left_y-right_y,self.image.get_width())/math.pi
debug("angle: "+str(int(angle)))
print(self.rect.left,self.rect.right)
self.rotate(angle)
def replicate(self):
if self.rect.left == 363:
return
self.rect.x += 1
def get_input(self):
self.replicate()
# keys = pygame.key.get_pressed()
# if keys[K_LEFT]:
# self.move.x = -self.velocity
# elif keys[K_RIGHT]:
# self.move.x = self.velocity
# else:
# self.move.x = 0
# if keys[K_UP]:
# self.move.y = -self.velocity
# elif keys[K_DOWN]:
# self.move.y = self.velocity
# else:
# self.move.y = 0
# self.rect.x += self.move.x
# self.rect.y += self.move.y
# if self.rect.left <= 0:
# self.rect.left = 0
# if self.rect.right >= SCREEN_WIDTH:
# self.rect.right = SCREEN_WIDTH
ship_sprite = pygame.sprite.GroupSingle()
ship_sprite.add(Ship())
while True:
screen.fill((200,210,255,0))
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
ship_sprite.update()
ship_sprite.draw(screen)
draw_water(screen,SCREEN_HEIGHT-300)
clock.tick(60)
pygame.display.update()
It's about accuracy. You can improve the result by storing the water level with floating point precision:
def draw_water(surface, dy):
amplitude = 35
global watter_levels
for x in range(SCREEN_WIDTH):
y = math.sin(x * 0.01) * amplitude + dy
watter_levels[x] = y
pygame.draw.aaline(surface, BLUE, (x, round(y)), (x, round(y)))
Furthermore you have to get the left and right from the "unrotated" rectangle:
class Ship(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
self.image = pygame.Surface((80,80),pygame.SRCALPHA)
self.image.fill('red')
self.rect = self.image.get_rect(topleft = (0, 0))
self.copy_img = self.image.copy()
self.copy_rect = pygame.Rect(self.rect)
self.move = pygame.math.Vector2(0, 0)
self.velocity = 8
def rotate(self, angle):
self.image = pygame.transform.rotate(self.copy_img, round(angle))
self.rect = self.image.get_rect(center = (self.copy_rect.center))
def update(self):
self.get_input()
self.copy_rect.bottom = round(get_water_level(self.copy_rect.centerx))
left_y = get_water_level(self.copy_rect.left)
right_y = get_water_level(self.copy_rect.right)
angle = math.degrees(math.atan2(left_y-right_y, self.copy_img.get_width()))
debug("angle: " + str(round(angle)))
print(self.copy_rect.left, self.copy_rect.right)
self.rotate(angle)
def replicate(self):
if self.copy_rect.left == 363:
return
self.copy_rect.x += 1
I have mute and unmute button on my main screen and the problem I'm having with is that when I press my mute button and it turns to a unmute button then when I play my game and die and I go back to the main screen, it turns it back to a mute button. I want to make it so that if I mute my game and I start it and die, it still a mute button, it does not revert to a unmute button. I have tried using a True and False statement also I have tried. https://gyazo.com/6b3d63d7615b07f2b4984d01ae239db5
My full code
import pygame,random
pygame.init()
width = 500
height = 600
# Screen width and height
window = pygame.display.set_mode((width,height))
# Name of the Screen
pygame.display.set_caption("Game")
# For off and on music
music_on = pygame.image.load("img/music_on.png")
music_on = pygame.transform.scale(music_on,(music_on.get_width()//2, music_on.get_height()//2))
music_off = pygame.image.load("img/music_off.png")
music_off = pygame.transform.scale(music_off,(music_off.get_width()//2, music_off.get_height()//2))
# Start screen
def text_objects(font,text):
textSurface = font.render(text,True,(0,0,0))
return textSurface, textSurface.get_rect()
def button(msg,x,y,w,h,ac,ic,action=None):
mouse = pygame.mouse.get_pos()
click = pygame.mouse.get_pressed()
if mouse[0] > x and y+h > mouse[1] > y:
pygame.draw.rect(window,ac,(x,y,w,h))
if click[0] == 1 and action != None:
action()
else:
pygame.draw.rect(window,ic,(x,y,w,h))
def quitgame():
pygame.quit()
def game2():
# part of making background shift
# player class
class Player:
def __init__(self,x,y,width,height,color):
self.x = x
self.y = y
self.width = width
self.height = height
self.color = color
self.rect = pygame.Rect(x,y,width,height)
def get_rect(self):
self.rect.topleft = (self.x,self.y)
return self.rect
def draw(self):
self.rect.topleft = (self.x,self.y)
pygame.draw.rect(window,self.color,self.rect)
# Button class
class button11:
def __init__(self,color,x,y,width,height,text=''):
self.color = color
self.x = x
self.y = y
self.width = width
self.height = height
self.text = text
self.over = False
def draw(self,window, outline=None):
# Call this method to draw button on screen
if outline:
pygame.draw.rect(window,outline(self.x-2,self.y-2,self.width+4,self.height+4),0)
pygame.draw.rect(window,self.color,(self.x,self.y,self.width,self.height),0)
if self.text != '':
font = pygame.font.SysFont("comicsans",60)
text = font.render(self.text,1,(0,0,0))
window.blit(text, (self.x + (self.width/2 - text.get_width()/2), self.y+ (self.height/2 - text.get_height()/2)))
def isOver(self,pos):
# Pos is mouse position or tuple of (x,y) coordinates
if pos[0] > self.x and pos[0] < self.x + self.width:
if pos[1] > self.y and pos[1] < self.y + self.height:
return True
return False
def playSoundIfMouseIsOver(self,pos,sound):
if self.isOver(pos):
if not self.over:
Hover.play()
self.over = True
else:
self.over = False
class Sweep:
def __init__(self,x,y,width,height,color):
self.x = x
self.y = y
self.width = width
self.height = height
self.color = color
self.speed = 2
self.rect = pygame.Rect(x,y,width,height)
def draw(self):
self.rect.topleft = (self.x,self.y)
pygame.draw.rect(window,self.color,self.rect)
# Color
white = (255,255,255)
Black = (0,0,0)
# Calss's cords,size, and color
playerman = Player(230,150,40,40,white)
right = Sweep(-600,0,600,800,Black)
right2 = Sweep(530,0,600,800,Black)
left1 = Sweep(-550,0,800,800,Black)
left2 = Sweep(250,0,800,800,Black)
sweeps = [right,right2,left1,left2]
font = pygame.font.Font("img/Bubble.ttf",60)
text = font.render("SPACE TO START!",True,(0,0,0))
textRect = text.get_rect()
textRect.center = ((250,400))
Sbutton = button11((0,255,0),431,16,40,50, '')
# Displaying class's in main loop
def redrawwindow():
window.fill((255,0,0))
# Drawing my classes and other things
playerman.draw()
window.blit(text,textRect)
if on:
window.blit(music_on,(420,10))
if off:
window.blit(music_off,(420,10))
for Sweep in sweeps:
Sweep.draw()
sound = True
mouseisover = True
switch = 1
Stimer = 0
off = False
on = True
timer = 0
fps = 35
clock = pygame.time.Clock()
run = True
while run:
clock.tick(fps)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
if event.type == pygame.MOUSEBUTTONDOWN:
pos = pygame.mouse.get_pos()
if switch == 1 and Sbutton.isOver(pos):
switch = 2
on = False
off = True
else:
if switch == 2 and Sbutton.isOver(pos):
switch = 1
on = True
off = False
timer += 1
keys = pygame.key.get_pressed()
if keys[pygame.K_SPACE] and timer >= 20:
Stimer += 1
if Stimer > 0 :
Stimer += 1
right.x += 20
right2.x -= 20
if Stimer >= 32:
main_loop()
Stimer = 0
left1.x -= 20
left2.x += 20
redrawwindow()
pygame.display.update()
pygame.quit()
def main_loop():
global lose
# Making both peipes separate
Pipe_distance = 830
# part of making background shift
bg_shift = 0
# player class
# player class
class Player:
def __init__(self,x,y,width,height,color):
self.x = x
self.y = y
self.width = width
self.height = height
self.color = color
self.speed = 5
self.JumpCount = False
self.isJump = 10
self.fall = 0
self.rect = pygame.Rect(x,y,width,height)
def get_rect(self):
self.rect.topleft = (self.x,self.y)
return self.rect
def draw(self):
self.rect.topleft = (self.x,self.y)
pygame.draw.rect(window,self.color,self.rect)
# Pipe class
class Pipe:
def __init__(self,x,y,width,height,color):
self.x = x
self.y = y
self.width = width
self.height = height
self.color = color
self.speed = 3
self.rect = pygame.Rect(x,y,width,height)
def get_rect(self):
self.rect.topleft = (self.x,self.y)
return self.rect
def draw(self):
self.rect.topleft = (self.x,self.y)
pygame.draw.rect(window,self.color,self.rect)
# Pipe2 class
class Pipe2:
def __init__(self,x,y,width,height,color):
self.x = x
self.y = y
self.width = width
self.height = height
self.color = color
self.speed = 3
self.rect = pygame.Rect(x,y,width,height)
def get_rect(self):
self.rect.topleft = (self.x,self.y)
return self.rect
def draw(self):
self.rect.topleft = (self.x,self.y)
pygame.draw.rect(window,self.color,self.rect)
class Sweep:
def __init__(self,x,y,width,height,color):
self.x = x
self.y = y
self.width = width
self.height = height
self.color = color
self.speed = 2
self.rect = pygame.Rect(x,y,width,height)
def draw(self):
self.rect.topleft = (self.x,self.y)
pygame.draw.rect(window,self.color,self.rect)
# Color
white = (255,255,255)
green = (0,255,0)
blue = (0,0,255)
Black = (0,0,0)
# Calss's cords,size, and color
playerman = Player(200,200,40,40,white)
pipe1 = Pipe(350,900,60,700,green)
pipe2 = Pipe2(350,-900,60,700,green)
pipe3 = Pipe(720,9900,60,700,white)
pipe4 = Pipe2(720,-9900,60,700,blue)
left1 = Sweep(-550,0,800,800,Black)
left2 = Sweep(250,0,800,800,Black)
# All my list
pipes = [pipe1,pipe3]
pipes2 = [pipe2,pipe4]
sweeps = [left1,left2]
# Point system
font = pygame.font.Font("img/CAT.ttf",60)
score = 0
text = font.render(""+str(score), True,(255,255,255))
textRect = text.get_rect()
textRect.center = ((250,60))
lose = False
def quitgame():
pygame.quit()
def unlose():
global lose
lose = False
def lost():
lfont = pygame.font.Font("img/CAT.ttf",60)
ltext = lfont.render("You Died",True,(255,255,255))
ltextRect = ltext.get_rect()
ltextRect.center = ((250,90))
lfont2 = pygame.font.Font("img/CAT.ttf",60)
ltext2 = lfont2.render("Score",True,(255,255,255))
ltextRect2 = ltext2.get_rect()
ltextRect2.center = ((250,510))
lfont3 = pygame.font.Font("img/CAT.ttf",50)
ltext3 = lfont3.render("Space To Return",True,(255,0,255))
ltextRect3 = ltext3.get_rect()
ltextRect3.center = ((250,270))
timer = 0
while lose:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
timer += 1
keys = pygame.key.get_pressed()
if keys[pygame.K_SPACE] and timer >= 20:
game2()
window.fill((0,0,0))
text = font.render(""+str(score), True,(255,255,255))
textRect.center = ((250,450))
window.blit(ltext,ltextRect)
window.blit(ltext2,ltextRect2)
window.blit(ltext3,ltextRect3)
window.blit(text,textRect)
pygame.display.update()
clock.tick(15)
# Displaying class's in main loop
def redrawwindow():
window.fill((0,0,0))
# Drawing my classes and other things
playerman.draw()
for Pipe in pipes:
Pipe.draw()
for Pipe2 in pipes2:
Pipe2.draw()
for Sweep in sweeps:
Sweep.draw()
window.blit(text,textRect)
# To make the game more difuclt
ptimer = 0
# for playing sprite when player jumps
# Making it so the rectangle dose not come for a whilw
Ptimer = 0
Ptimer2 = 0
spcdown = False
sound = True
# for making firse play once
fps = 35
clock = pygame.time.Clock()
run = True
while run:
clock.tick(fps)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
# Making most of my classes move
for Pipe in pipes:
Pipe.x -= Pipe.speed
for Pipe2 in pipes2:
Pipe2.x -= Pipe2.speed
for Pipe2 in pipes2:
if Pipe2.x <= -200:
Pipe2.x = 550
left1.x -= 20
left2.x += 20
# Randomizing pipe
for Pipe in pipes:
if Pipe.x <= -200:
Pipe.x = 550
Pipe.y = random.randint(150,500)
pipe2.y = pipe1.y - Pipe_distance
pipe4.y = pipe3.y - Pipe_distance
# Making the game faster
ptimer += 1
if ptimer == 10000:
for Pipe in pipes:
for Pipe2 in pipes2:
Pipe.speed += 1
Pipe2.speed += 1
bg_shift += 3
for Pipe in pipes:
if playerman.rect.colliderect(Pipe.rect):
lose = True
lost()
for Pipe2 in pipes2:
if playerman.rect.colliderect(Pipe2.rect):
lose = True
lost()
keys = pygame.key.get_pressed()
if not keys[pygame.K_SPACE]:
spcdown = False # space released
if keys[pygame.K_SPACE]:
Jumping = 1
if not spcdown:
spcdown = True
collide = False
playerman.y += playerman.speed
# bird moving
if not playerman.isJump:
# [...]
# the bird is allowed to jump even if it is not colliding:
if keys[pygame.K_SPACE]:
playerman.isJump = True
if collide:
playerman.fall = 0
else:
if playerman.JumpCount > 0:
playerman.y -= (playerman.JumpCount*abs(playerman.JumpCount))*0.3
playerman.JumpCount -= 1
else:
playerman.JumpCount = 10
# if K_SPACE is pressed, then the bird keeps jumping
if not keys[pygame.K_SPACE]:
playerman.isJump = False
redrawwindow()
pygame.display.update()
pygame.quit()
unlose()
game2()
main_loop()
The problem is probably caused by using two separate variables to control the state of the sound:
if on:
window.blit(music_on,(420,10))
if off:
window.blit(music_off,(420,10))
I suggest using only a single, descriptive, variable name:
if ( sound_muted ):
window.blit( music_on, (420,10) ) # show "un-mute" button
else:
window.blit( music_off, (420,10) ) # show "mute" button
And change that when the image is clicked:
if event.type == pygame.MOUSEBUTTONDOWN:
pos = pygame.mouse.get_pos()
if Sbutton.isOver(pos):
sound_muted = not sound_muted # mute or un-mute the sound.
Firts I am french so excuse-me for my english. I have recently discoverd pygame and I love that so decided to create a rpg on pygame and... I have a little problem : with many, many difficulty I made a scrolling system on my pygame's rpg I evn do a system how make sure player's image gets back when he go up, puts himself in profile ...
BUT (a big but) my player's image don't move, the scrolling, move and the player's rect also, I don't know I can solve that so please help me !!!!! The main.py file :
from game import Game
from level import *
pygame.init()
lvl = Level()
screen = pygame.display.set_mode((1024, 768))
pygame.display.set_caption("RPG")
game = Game()
cam = Camera(1024, 768)
running = True
lvl.generer()
print(game.player.rect)
clock = pygame.time.Clock()
while running:
cam.update(game.player)
#print(cam.rect.topleft)
if game.pressed.get(pygame.K_RIGHT) and game.player.rect.x + game.player.rect.width < 1080:
game.player.move_right()
lvl.afficher(screen, 0, 0, cam.x, cam.y)
#print(game.player.rect.x)
elif game.pressed.get(pygame.K_LEFT) and game.player.rect.x > 0:
game.player.move_left()
lvl.afficher(screen, 0, 0, cam.x, cam.y)
#print(game.player.rect.x)
elif game.pressed.get(pygame.K_DOWN):
game.player.move_down()
lvl.afficher(screen, 0, 0, cam.x, cam.y)
#screen.scroll(0, -game.player.velocity)
#print(game.player.rect.y)
elif game.pressed.get(pygame.K_UP):
game.player.move_up()
lvl.afficher(screen, 0, 0, cam.x, cam.y)
#screen.scroll(0, game.player.velocity)
#print(game.player.rect.y)
#print(cam.rect.x, cam.rect.y)
#print(cam.rect)
screen.blit(game.player.image, game.player.rect)
print(game.player.rect)
pygame.display.flip()
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
pygame.quit()
elif event.type == pygame.KEYDOWN:
game.pressed[event.key] = True
elif event.type == pygame.KEYUP:
game.pressed[event.key] = False```
the player.py class :
```import pygame
class Player(pygame.sprite.Sprite):
def __init__(self, game):
super(Player, self).__init__()
self.game = game
self.health = 100
self.maxHealth = 100
self.attack = 10
self.velocity = 10
self.dimension = (64, 88)
self.image = pygame.image.load("assets/player/player_face/player_face.png")
self.original_image = pygame.image.load("assets/player/player_face/player_face.png")
self.image = pygame.transform.scale(self.image, self.dimension)
self.rect = self.image.get_rect()
self.rect.x = 512
self.rect.y = 384
self.face = [pygame.image.load("assets/player/player_face/player/sprite_00.png"), pygame.image.load("assets/player/player_face/player/sprite_01.png"), pygame.image.load("assets/player/player_face/player/sprite_02.png"), pygame.image.load("assets/player/player_face/player/sprite_03.png"), pygame.image.load("assets/player/player_face/player/sprite_04.png"), pygame.image.load("assets/player/player_face/player/sprite_05.png"), pygame.image.load("assets/player/player_face/player/sprite_06.png"), pygame.image.load("assets/player/player_face/player/sprite_07.png"), pygame.image.load("assets/player/player_face/player/sprite_08.png"), pygame.image.load("assets/player/player_face/player/sprite_09.png")]
def move_right(self):
self.rect.x += self.velocity
self.image = pygame.image.load("assets/player/player_profileLeft/player_profile_left.png")
self.image = pygame.transform.scale(self.image, self.dimension)
def move_left(self):
self.rect.x -= self.velocity
self.image = pygame.image.load("assets/player/player_profileRight/player_profile_right.png")
self.image = pygame.transform.scale(self.image, self.dimension)
def move_down(self):
self.rect.y += self.velocity
#self.image = pygame.image.load("assets/player/player_face/player_face.png")
#self.image = pygame.transform.scale(self.image, self.dimension)
i = 0
for elt in self.face:
self.image = self.face[i]
print("lol")
self.image = pygame.transform.scale(self.image, self.dimension)
i += 1
def move_up(self):
self.rect.y -= self.velocity
self.image = pygame.image.load("assets/player/player_back/player_dos.png")
self.image = pygame.transform.scale(self.image, self.dimension)
the level.py class :
from pygame.locals import *
from player import *
class Camera:
def __init__(self, widht, height):
self.rect = pygame.Rect(0, 0, widht, height)
self.widht = widht
self.height = height
self.topleft = list(self.rect.topleft)
self.x = self.topleft[0]
self.y = self.topleft[1]
def update(self, target):
self.rect.y = -target.rect.y + int(769 / 2)
self.rect.x = -target.rect.x + int(1024 / 2)
self.topleft = list(self.rect.topleft)
self.x = self.topleft[0]
self.y = self.topleft[1]
self.rect = pygame.Rect(self.rect.x, self.rect.y, self.widht, self.height)
#self.rect.topleft_x = self.rect.topleft(0)
#self.coo = (0, 0)
class Level:
def __init__(self):
self.structure = 0
def generer(self):
with open("niveau.txt", "r") as fichier:
structure_niveau = []
for ligne in fichier:
ligne_niveau = []
for sprite in ligne:
if sprite != '\n':
ligne_niveau.append(sprite)
structure_niveau.append(ligne_niveau)
self.structure = structure_niveau
def afficher(self, fenetre, x, y, camLeftX, camLeftY):
tailleSprite = 64
#Camera.__init__(self, x, y)
grass = pygame.image.load("assets/bloc/grass.png").convert_alpha()
tree = pygame.image.load("assets/bloc/tree_grass.png").convert_alpha()
no_texture = pygame.image.load("assets/bloc/no_texture.png")
num_ligne = 0
for ligne in self.structure:
num_case = 0
for sprite in ligne:
x = num_case * tailleSprite - camLeftX
y = num_ligne * tailleSprite - camLeftY
if sprite == 'G':
fenetre.blit(grass, (x, y))
elif sprite == 'T':
fenetre.blit(tree, (x, y))
#print(self.x, self.y)
else:
fenetre.blit(no_texture, (x, y))
num_case += 1
num_ligne += 1```
Ok I just found the solution but It's making an other problem I'll ask the question on a other post. At x = num_case * tailleSprite - camLeftX and y = num_ligne * tailleSprite - camLeftY on level.py just replace the - by a +
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I was working on a movement animations since I saw a youtuber explaining how to do it, but I'm getting this error:
TypeError: argument 1 must be pygame.Surface, not list
My code is about 500 lines.
# Pygame Template - skeleton for a new pygame project
import pygame
import random
import os
from os import path
vec = pygame.math.Vector2
width = 800
height = 600
FPS = 60
POWERUP_TIME = 5000
title = 'Parkourse'
# Player properties
player_acceleration = 0.5
player_friction = -0.12
player_gravity = 0.8
player_jump = 10
# Starting platforms
platforms_list = [(0,height-40,width,50), # Ground
(0,0,800,10), # Top
(0,0,10,600), # Left Border
(790,height-400,10,600),# Right Border
(250,height - 160,width-200,10), # Floor 1
(0,height - 280,width-200,10), # Floor 2
(250,height - 400,width-100,10)] # Floor 3
# Define Colors
white = (255,255,255)
black = (0,0,0)
red = (255,0,0)
green = (0,255,0)
blue = (0,0,255)
# set up assets folders
game_folder = os.path.dirname(__file__)
image_folder = os.path.join(game_folder, "Image")
sound_folder = os.path.join(game_folder, "Sound")
# Initialize pygame and create window
pygame.init()
pygame.mixer.init()
screen = pygame.display.set_mode((width,height))
pygame.display.set_caption(title)
clock = pygame.time.Clock()
# Load all game graphics
background = pygame.image.load(path.join(image_folder, "background.png")).convert()
background_rect = background.get_rect()
no_mvmt_0 = pygame.image.load(path.join(image_folder,"no_mvmt_0.png")).convert()
no_mvmt_1 = pygame.image.load(path.join(image_folder,"no_mvmt_1.png")).convert()
running_0 = pygame.image.load(path.join(image_folder,"running_0.png")).convert()
running_1 = pygame.image.load(path.join(image_folder,"running_1.png")).convert()
jumping_0 = pygame.image.load(path.join(image_folder,"jumping_0.png")).convert()
mini_no_mvmt = pygame.transform.scale(no_mvmt_0, (25,48))
mini_no_mvmt.set_colorkey(white)
scissors = pygame.image.load(path.join(image_folder,"scissors.png")).convert()
mob_left = pygame.image.load(path.join(image_folder,"mob_left.png")).convert()
power_upper_image = {}
power_upper_image['shield_0'] = pygame.image.load(path.join(image_folder,"shield_upper_0.png")).convert()
power_upper_image['shield_1'] = pygame.image.load(path.join(image_folder,"shield_upper_1.png")).convert()
power_upper_image['shield_2'] = pygame.image.load(path.join(image_folder,"shield_upper_2.png")).convert()
power_upper_image['life'] = pygame.image.load(path.join(image_folder,"life_upper.png")).convert()
power_upper_image['power'] = pygame.image.load(path.join(image_folder,"power.png")).convert()
explosion_animation = {}
explosion_animation['normal']=[]
explosion_animation['small']=[]
explosion_animation['player']=[]
for explosion in range(5):
explose = 'explosion_{}.png'.format(explosion)
image = pygame.image.load(path.join(image_folder, explose)).convert()
image.set_colorkey(white)
image.set_colorkey(black)
image_normal = pygame.transform.scale(image, (80,80))
explosion_animation['normal'].append(image_normal)
image_small = pygame.transform.scale(image, (30, 30))
explosion_animation['small'].append(image_small)
death = 'dying_{}.png'.format(explosion)
image = pygame.image.load(path.join(image_folder, death)).convert()
image.set_colorkey(white)
explosion_animation['player'].append(image)
#Load all game sounds
scream_sound = []
for scream in ["slightscream_0.wav", "slightscream_1.wav", "slightscream_2.wav",
"slightscream_3.wav", "slightscream_4.wav", "slightscream_5.wav",
"slightscream_6.wav", "slightscream_7.wav", "slightscream_8.wav",
"slightscream_9.wav", "slightscream_10.wav", "slightscream_11.wav",
"slightscream_12.wav", "slightscream_13.wav", "slightscream_14.wav"]:
scream_sound.append(pygame.mixer.Sound(path.join(sound_folder,scream)))
shoot_sound = pygame.mixer.Sound(path.join(sound_folder,"shoot.wav"))
shield = pygame.mixer.Sound(path.join(sound_folder,"shield.wav"))
life = pygame.mixer.Sound(path.join(sound_folder,"life.wav"))
special_power = pygame.mixer.Sound(path.join(sound_folder,"special_power.wav"))
death_sound = pygame.mixer.Sound(path.join(sound_folder,"death.ogg"))
explosion_sound = []
for sound in ["explosion.wav", "explosion_2.wav"]:
explosion_sound.append(pygame.mixer.Sound(path.join(sound_folder, sound)))
pygame.mixer.music.load(path.join(sound_folder,"gameplay.ogg"))
pygame.mixer.music.set_volume(0.6)
font_name = pygame.font.match_font('arial')
def draw_text (surf, text,color,size, x, y):
font = pygame.font.Font(font_name, size)
text_surface = font.render(text, True, color)
text_rect = text_surface.get_rect()
text_rect.midtop = (x, y)
surf.blit(text_surface, text_rect)
def newmob():
m = Mobs()
all_sprites.add(m)
mobs.add(m)
def draw_shield_bar(screen, x,y,percentage):
if percentage < 0:
percentage = 0
bar_lenght = 100
bar_height = 10
fill = (percentage / 100) * bar_lenght
outline_rect = pygame.Rect(x,y,bar_lenght,bar_height)
fill_rect = pygame.Rect(x,y,fill, bar_height)
pygame.draw.rect(screen, green, fill_rect)
pygame.draw.rect(screen, black, outline_rect, 2) # 2 is the the number of pixels
# of how wide you want the outline
# of the rectangle to be
def draw_lives (surface, x, y, lives, image):
for i in range(lives):
image_rect = image.get_rect()
image_rect.x = x + 30 * i
image_rect.y = y
surface.blit(image, image_rect)
score = 0
def show_game_over_screen():
screen.blit(background, background_rect)
draw_text(screen, "Dang..!",red,100, width/2, 200)
draw_text(screen, "Score: " + str(score),blue,30, width/2, 330)
draw_text(screen, "Press any key to retry",blue,30, width/2, 390)
pygame.display.flip()
waiting = True
while waiting:
clock.tick(FPS)
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
if event.type == pygame.KEYUP:
waiting = False
def show_start_screen():
screen.blit(background, background_rect)
draw_text(screen,"Parkourse!", green, 100, width/2, 200)
draw_text(screen, "Use the arrow keys to move, S to fire, and space to Jump",blue,30, width/2, 330)
draw_text(screen, "Press any key to begin",blue,30, width/2, 390)
pygame.display.flip()
waiting = True
while waiting:
clock.tick(FPS)
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
if event.type == pygame.KEYUP:
waiting = False
class Player (pygame.sprite.Sprite):
# Sprite for the player
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.load_movement_images()
self.image = self.standing_frame[0]
self.rect = self.image.get_rect()
self.pos = vec(50,500)
self.vel = vec(0,0)
self.acc = vec(0,0)
self.shield = 100
self.lives = 3
self.hidden = False
self.hide_timer = pygame.time.get_ticks()
self.power = 1
self.power_timer = pygame.time.get_ticks()
self.running = False
self.jumping = False
self.current_frame = 0
self.last_update = 0
def load_movement_images(self):
self.standing_frame = [no_mvmt_0, no_mvmt_1]
self.running_frame_right = [running_0,running_1]
self.running_frame_left = []
for frame in self.standing_frame:
frame.set_colorkey(white)
for frame in self.running_frame_right:
self.running_frame_left.append(pygame.transform.flip(frame,True,False)) # True is horizontaly, False is vertically
frame.set_colorkey(white)
self.jumping_frame = jumping_0
self.jumping_frame.set_colorkey(white)
def animate(self):
now = pygame.time.get_ticks()
if not self.jumping and not self.running:
if now - self.last_update > 350:
self.last_update = now
self.current_frame = (self.current_frame + 1) % len(self.standing_frame)
self.image = self.standing_frame
def jump(self):
# Jump only if standing on a Platform
self.rect.x +=1
hits = pygame.sprite.spritecollide(player,platforms, False)
self.rect.x -= 1
if hits:
self.vel.y = - player_jump
def update(self):
self.animate()
# timeout for powerups
if self.power >=2 and pygame.time.get_ticks() - self.power_time > POWERUP_TIME:
self.power -= 1
self.power_time = pygame.time.get_ticks()
# unhide if hidden
if self.hidden and pygame.time.get_ticks() - self.hide_timer > 1000:
self.hidden = False
self.pos = vec(30, 400)
self.acc = vec(0,player_gravity)
keystate = pygame.key.get_pressed()
if keystate[pygame.K_LEFT] or keystate[pygame.K_a]:
self.acc.x = -player_acceleration
if keystate[pygame.K_RIGHT] or keystate[pygame.K_d]:
self.acc.x = player_acceleration
if keystate[pygame.K_SPACE]:
player.jump()
# apply friction
self.acc.x += self.vel.x * player_friction
# equations of motions
self.vel += self.acc
self.pos += self.vel + 0.5 * self.acc
# wrap around the sides of the screen
if self.pos.x > 750:
self.pos.x = 750
if self.pos.x <= 0:
self.pos.x = 25
self.rect.midbottom = self.pos
def powerup(self):
self.power += 1
self.power_time = pygame.time.get_ticks()
def shoot(self):
if self.power == 1:
bullet = Bullet(self.pos.x + 5, self.pos.y - 20)
all_sprites.add(bullet)
bullets.add(bullet)
shoot_sound.play()
if self.power >= 2:
bullet1 = Bullet(self.pos.x + 5, self.pos.y - 20)
bullet2 = Bullet(self.pos.x + 35, self.pos.y -20)
all_sprites.add(bullet1)
all_sprites.add(bullet2)
bullets.add(bullet1)
bullets.add(bullet2)
shoot_sound.play()
def hide(self):
# hide the player temporarily
self.hidden = True
self.hide_timer = pygame.time.get_ticks()
self.pos = vec(0, 6000)
class Bullet(pygame.sprite.Sprite):
def __init__(self, x, y):
pygame.sprite.Sprite.__init__(self)
self.image = scissors
self.rect = self.image.get_rect()
self.image.set_colorkey(white)
self.image = pygame.transform.scale(scissors, (30,15))
self.rect.bottom = y
self.rect.centerx = x
self.speedx = 10
def update(self):
self.rect.x += self.speedx
# kill if it moves off the top of the screen
if self.rect.bottom < 0:
self.kill()
class Mobs(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = mob_left
self.rect = self.image.get_rect()
self.image.set_colorkey(white)
self.rect.x = random.randrange(0,800)
self.rect.y = 530
self.speedx = 2
def update(self):
self.rect.x -= self.speedx
if self.rect.right < 0:
self.rect.x = 800
class Explosion(pygame.sprite.Sprite):
def __init__(self, center, size, frame):
pygame.sprite.Sprite.__init__(self)
self.size = size
self.image = explosion_animation[self.size][0]
self.rect = self.image.get_rect()
self.rect.center = center
self.frame = 0
self.last_update = pygame.time.get_ticks()
self.frame_rate = frame
def update(self):
now = pygame.time.get_ticks()
if now - self.last_update > self.frame_rate:
self.last_update = now
self.frame += 1
if self.frame == len(explosion_animation[self.size]):
self.kill()
else:
center = self.rect.center
self.image = explosion_animation[self.size][self.frame]
self.rect = self.image.get_rect()
self.rect.center = center
class Normal_Power(pygame.sprite.Sprite):
def __init__(self, center):
pygame.sprite.Sprite.__init__(self)
self.type = random.choice(['shield_0','shield_1','shield_2'])
self.image = power_upper_image[self.type]
self.rect = self.image.get_rect()
self.image.set_colorkey(white)
self.rect.center = center
class Special_Power(pygame.sprite.Sprite):
def __init__(self, center):
pygame.sprite.Sprite.__init__(self)
self.type = random.choice(['life','power'])
self.image = power_upper_image[self.type]
self.rect = self.image.get_rect()
self.image.set_colorkey(white)
self.rect.center = center
class Platform(pygame.sprite.Sprite):
def __init__(self, x, y, w, h):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.Surface((w, h))
self.image.fill(black)
self.rect = self.image.get_rect()
self.rect.x = x
self.rect.y = y
pygame.mixer.music.play(loops=-1) # loops = -1 means that pygame will restart the song when it's finished
# Game loop
running = True
new_game = True
game_over = False
while running:
if new_game:
show_start_screen()
new_game = False
all_sprites = pygame.sprite.Group()
platforms = pygame.sprite.Group()
for plat in platforms_list:
p = Platform (*plat)
all_sprites.add(p)
platforms.add(p)
mobs = pygame.sprite.Group()
player = Player()
all_sprites.add(player)
bullets = pygame.sprite.Group()
powerups = pygame.sprite.Group()
for i in range(1):
newmob()
score = 0
if game_over:
show_game_over_screen()
game_over = False
all_sprites = pygame.sprite.Group()
platforms = pygame.sprite.Group()
for plat in platforms_list:
p = Platform (*plat)
all_sprites.add(p)
platforms.add(p)
mobs = pygame.sprite.Group()
player = Player()
all_sprites.add(player)
bullets = pygame.sprite.Group()
powerups = pygame.sprite.Group()
for i in range(1):
newmob()
score = 0
# Keep loop running at the right speed
clock.tick(FPS)
# Process input (events)
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_s:
player.shoot()
# Updates
all_sprites.update()
# check if player hits a platform - only if falling
if player.vel.y > 0:
hits = pygame.sprite.spritecollide(player,platforms,False)
if hits:
player.pos.y = hits[0].rect.top
player.vel.y = 0
# check to see if a bullet hit a mob
hits = pygame.sprite.groupcollide(mobs,bullets,True,True)
for hit in hits:
score += 1
random.choice(explosion_sound).play()
expl = Explosion(hit.rect.center, 'normal', 50)
all_sprites.add(expl)
if random.random() > 0.75:
power = Normal_Power(hit.rect.center)
all_sprites.add(power)
powerups.add(power)
if random.random() > 0.90:
lives = Special_Power(hit.rect.center)
all_sprites.add(lives)
powerups.add(lives)
newmob()
# check to see if the mob hit the player
hits = pygame.sprite.spritecollide(player, mobs,True)
for hit in hits:
random.choice(explosion_sound).play()
player.shield -= 25
newmob()
expl = Explosion(hit.rect.center, 'small', 50)
all_sprites.add(expl)
if player.shield <= 0:
death_sound.play()
death_animation = Explosion(player.rect.center, 'player', 100)
all_sprites.add(death_animation)
player.hide()
player.lives -= 1
player.shield = 100
else:
random.choice(scream_sound).play()
# check if the player hit a powerup
hits = pygame.sprite.spritecollide(player, powerups, True)
for hit in hits:
if hit.type == 'shield_0':
player.shield += 5
if player.shield >= 100:
player.shield = 100
shield.play()
if hit.type == 'shield_1':
player.shield += 20
if player.shield >= 100:
player.shield = 100
shield.play()
if hit.type == 'shield_2':
player.shield += 20
if player.shield >= 100:
player.shield = 100
shield.play()
if hit.type == 'life':
player.lives += 1
if player.lives >= 3:
player.lives = 3
life.play()
if hit.type == 'power':
special_power.play()
player.powerup()
# if the player died and the explosion finished playing
if player.lives == 0 and not death_animation.alive():
game_over = True
# Draw / Render
screen.fill(white)
screen.blit(background, background_rect)
all_sprites.draw(screen)
draw_text(screen,str(score),red,30, width/ 2, 30)
draw_text(screen,"Score:",red,30, width / 2, 3)
draw_shield_bar(screen,90,20, player.shield)
draw_lives(screen,95,40,player.lives, mini_no_mvmt)
# *after* drawing everything, flip the display
pygame.display.flip()
pygame.quit()
quit()
The error is caused by a sprite in your all_sprites group that has a list as its self.image attribute. I've just printed the sprites before the all_sprites.draw(screen) line
for sprite in all_sprites:
print(sprite, sprite.image)
and it was the player sprite which had a list as its image.
<Player sprite(in 1 groups)> [<Surface(40x25x32 SW)>, <Surface(40x25x32 SW)>]
In the load_movement_images method you define self.standing_frame as a list of two images/pygame.Surfaces and in __init__ you set self.image to the first item of that list. But in the animate method you set self.image to the whole list instead of the active image self.image = self.standing_frame and that leads to the error.
class Player (pygame.sprite.Sprite):
# Sprite for the player
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.load_movement_images()
# self.image is the first image in the
# self.standing_frame list.
self.image = self.standing_frame[0]
# ...
def load_movement_images(self):
self.standing_frame = [no_mvmt_0, no_mvmt_1]
# ...
def animate(self):
now = pygame.time.get_ticks()
if not self.jumping and not self.running:
if now - self.last_update > 350:
self.last_update = now
self.current_frame = (self.current_frame + 1) % len(self.standing_frame)
# Here you set the self.image to the self.standing_fram list instead one image.
self.image = self.standing_frame
# It should be:
# self.image = self.standing_frame[self.current_frame]
I am writing a game with pygame which involves two player-controlled tanks which go around a brick map with their own health bars and shoot each other with one kind of bullet. From what I can tell, everything else is working, but I am having trouble determining which surface to draw the bricks, tanks, and bullets on: the "background" or the "screen" (the bricks do not change during the game, only the tanks and bullets). I tried drawing everything but the health bars on the background, but that just resulted in a black screen which only displayed the health bars. I then drew everything directly onto the screen and that displays everything correctly at first, but when the tanks move around, the screen doesn't refresh (I get many many tank images overlapping each other as the tank moves) and the bullets do not fire properly as a result. The code is below but the main() method is at the very bottom and that is what is causing errors. The "effects.py" file that is imported at the very top contains just the bullets and "booms" and "bombs" classes which are just special effects but aren't used so far in the main() method so they can be ignored.
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()
My suggestion is to make a global screen variable (instead of being wrapped inside a function, and generate a single city image, with the bricks added to it. Since those are all the components that do not change, this can be blitted to the screen every time the frame is refreshed.
After that, on each frame, the tank (with health bar and other stuff) and bullets can be blitted directly to the screen variable.
It is probably simplest to just do pygame.display.flip() after all of the blitting is done, but keeping an array of pygame.Rects representing blit positions and then keeping the old blit Rects and then doing something like:
old_rects = current_rects
current_rects = []
#make blits, collect Rects in current_rects
pygame.display.update(current_rects + old_rects)
This way, pygame.display.update() can be used (since it is more efficient), and there won't be problems with no refreshing.
I hope this works and that you can implement something like this.