adding a def main to the end of my pong game code - python

I'm trying to add a def main to the end of my pong game to make it easier to read, but i've ran into problems trying to do that. When I add the def main, I just get a black screen, but without it I get the whole game.
import pygame
SCR_WID, SCR_HEI = 640, 480
class Player():
def __init__(self):
self.x, self.y = 16, SCR_HEI/2
self.speed = 3
self.padWid, self.padHei = 8, 64
self.score = 0
self.scoreFont = pygame.font.Font("imagine_font.ttf", 64)
def scoring(self):
scoreBlit = self.scoreFont.render(str(self.score), 1, (255, 255, 255))
screen.blit(scoreBlit, (32, 16))
if self.score == 10:
print ("player 1 wins!")
exit()
def movement(self):
keys = pygame.key.get_pressed()
if keys[pygame.K_w]:
self.y -= self.speed
elif keys[pygame.K_s]:
self.y += self.speed
if self.y <= 0:
self.y = 0
elif self.y >= SCR_HEI-64:
self.y = SCR_HEI-64
def draw(self):
pygame.draw.rect(screen, (255, 255, 255), (self.x, self.y, self.padWid, self.padHei))
class Enemy(Player):
def __init__(self):
self.x, self.y = SCR_WID-16, SCR_HEI/2
self.speed = 3
self.padWid, self.padHei = 8, 64
self.score = 0
self.scoreFont = pygame.font.Font("imagine_font.ttf", 64)
def scoring(self):
scoreBlit = self.scoreFont.render(str(self.score), 1, (255, 255, 255))
screen.blit(scoreBlit, (SCR_HEI+92, 16))
if self.score == 10:
print ("Player 2 wins!")
exit()
def movement(self):
keys = pygame.key.get_pressed()
if keys[pygame.K_UP]:
self.y -= self.speed
elif keys[pygame.K_DOWN]:
self.y += self.speed
if self.y <= 0:
self.y = 0
elif self.y >= SCR_HEI-64:
self.y = SCR_HEI-64
def draw(self):
pygame.draw.rect(screen, (255, 255, 255), (self.x, self.y, self.padWid, self.padHei))
class Ball():
def __init__(self):
self.x, self.y = SCR_WID/2, SCR_HEI/2
self.speed_x = -3
self.speed_y = 3
self.size = 8
def movement(self):
self.x += self.speed_x
self.y += self.speed_y
#wall col
if self.y <= 0:
self.speed_y *= -1
elif self.y >= SCR_HEI-self.size:
self.speed_y *= -1
if self.x <= 0:
self.__init__()
enemy.score += 1
elif self.x >= SCR_WID-self.size:
self.__init__()
self.speed_x = 3
player.score += 1
##wall col
#paddle col
#player
for n in range(-self.size, player.padHei):
if self.y == player.y + n:
if self.x <= player.x + player.padWid:
self.speed_x *= -1
break
n += 1
#enemy
for n in range(-self.size, enemy.padHei):
if self.y == enemy.y + n:
if self.x >= enemy.x - enemy.padWid:
self.speed_x *= -1
break
n += 1
##paddle col
def draw(self):
pygame.draw.rect(screen, (255, 255, 255), (self.x, self.y, 8, 8))
SCR_WID, SCR_HEI = 640, 480
screen = pygame.display.set_mode((SCR_WID, SCR_HEI))
pygame.display.set_caption("Pong")
pygame.font.init()
clock = pygame.time.Clock()
FPS = 60
def main():
ball = Ball()
player = Player()
enemy = Enemy()
while True:
#process
for event in pygame.event.get():
if event.type == pygame.QUIT:
print ("Game exited by user")
exit()
##process
#logic
ball.movement()
player.movement()
enemy.movement()
##logic
#draw
screen.fill((0, 0, 0))
ball.draw()
player.draw()
player.scoring()
enemy.draw()
enemy.scoring()
##draw
#_______
pygame.display.flip()
clock.tick(FPS)
main()

The call for main() on the end should be
if __name__ == "__main__":
main()
So that you can run your code and get the function to run. Also your indentation seems a little off. Is your code structured correctly with regard to spaces?

As already answered, you should insert the following statement at the end of the script:
if __name__ == "__main__":
main()
This answer will give you more info about the meaning of that statement.
What does if __name__ == "__main__": do?
In short, it tells the interpreter what it has to do with the function main():
1) Run it automatically if the file has been executed as stand alone script.
2) Don't run if the file has been imported as module from another script.
In your case, the wanted behaviour is the number one.

Related

My collision detection isn't working and way to laggy

So here's just the base function:
def xCollision(self):
for tile in tiles:
if tile.colliderect(self.rect):
if self.x_vel >= 1:
self.rect.right = tile.left
elif self.x_vel <= -1:
self.rect.left = tile.right
def yCollision(self):
for tile in tiles:
if tile.colliderect(self.rect):
if self.y_vel >= 1:
self.rect.bottom = tile.top
elif self.y_vel <= -1:
self.rect.top = tile.bottom
This is inside the Player class.
Now, when i try this my frames go down to around 4 fps and it also isn't working.
About it not working it has to do something with the self.rect.something = tile.something because when i replace it with print() it prints whatever.
Here is the entire code for reference, And yes i just started out so don't think its gonna be any good ok?
import pygame
import random
import math
import time
# Initialize Pygame
pygame.init()
pygame.mixer.init()
# Set the size of the window
size = (900, 600)
screen = pygame.display.set_mode(size)
# Set the title of the window
pygame.display.set_caption("Classes testing")
clock = pygame.time.Clock()
fps = 60
pygame.mixer.music.load('PewPewProject/Retro Platform.wav')
pygame.mixer.music.set_volume(0.1)
pygame.mixer.music.play(-1)
pop_sound = pygame.mixer.Sound("PewPewProject/vine-boom.wav")
pop_sound.set_volume(0.5)
level = [
['1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1'],
['1','E','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','1'],
['1','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','1'],
['1','0','0','0','0','0','0','0','0','0','0','0','0','0','0','E','0','0','0','1'],
['1','0','0','0','1','1','1','0','0','0','0','0','0','0','0','0','0','0','0','1'],
['1','0','0','0','0','1','0','0','0','0','0','0','0','0','0','0','0','0','0','1'],
['1','0','0','1','0','1','0','0','0','0','0','0','0','0','E','0','0','0','0','1'],
['1','0','0','1','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','1'],
['1','E','1','1','1','0','0','0','0','0','0','0','0','0','0','0','0','0','0','1'],
['1','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','1'],
['1','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','1'],
['1','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','1'],
['1','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','1'],
['1','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','1'],
['1','0','0','0','0','0','0','0','0','E','0','0','0','0','0','0','0','0','0','1'],
['1','0','0','0','0','0','0','0','0','1','1','1','0','1','0','0','0','0','0','1'],
['1','0','0','0','0','0','0','0','0','1','0','0','0','1','0','0','0','0','0','1'],
['1','0','0','0','0','0','0','0','0','1','0','1','1','1','0','E','0','0','0','1'],
['1','0','0','0','0','0','0','0','0','1','0','1','S','1','0','0','0','0','0','1'],
['1','0','0','0','0','0','0','0','0','1','0','0','0','1','0','0','0','0','0','1'],
['1','0','0','E','0','0','0','0','0','1','1','1','1','1','0','0','0','0','0','1'],
['1','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','1'],
['1','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','1'],
['1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1'],
]
tilex, tiley = [0, 0]
tilex_offset, tiley_offset = [0, 0]
tile_size = 50
tilemap = pygame.image.load('PewPewProject/tilemap.png')
tiles = []
collision_tiles = []
enemy_spawns = []
def Build_Level():
global tiley,tilex
tiley = -1
for rows in level:
tilex = -1
tiley += 1
for tile in rows:
tilex += 1
if tile == '1':
tile_rect = pygame.draw.rect(screen, (100, 100, 100), (tilex*tile_size+tilex_offset, tiley*tile_size+tiley_offset, tile_size, tile_size))
tiles.append(tile_rect)
elif tile == '0':
pass
elif tile == 'E':
enemy_spawns.append([tilex, tiley])
elif tile == 'S':
pygame.draw.rect(screen, (50, 255, 100), (tilex*tile_size+tilex_offset, tiley*tile_size+tiley_offset, tile_size, tile_size))
elif tile == 'R':
pygame.draw.rect(screen, (255, 50, 50), (tilex*tile_size+tilex_offset, tiley*tile_size+tiley_offset, tile_size, tile_size))
else:
print("Wrong Map Input")
def random_except(start, end, exception_start, exception_end):
num = random.randint(start, end)
while num >= exception_start and num <= exception_end:
num = random.randint(start, end)
return num
class Player:
def __init__(self, health, speed, x, y, size, healthboost, collision_tiles):
self.speed = speed
self.x = x
self.y = y
self.y_vel = 0
self.x_vel = 0
self.size = size
self.hitbox = pygame.draw.rect(screen, (230, 100, 100), (self.x, self.y, self.size, self.size))
self.gunsurface = pygame.Surface((90, 25), pygame.SRCALPHA)
self.healthboost = healthboost
self.health = health * healthboost
self.rotated_gunsurface = self.gunsurface
self.gunsurface.fill((150, 150, 150))
self.gunrect = self.gunsurface.get_rect()
self.rect = self.hitbox
self.projectiles = [Projectile(-100, 0, 0)]
self.last_shot_time = 0
self.cooldown = 0.5
self.is_slowed = False
self.alive = True
def xCollision(self):
for tile in tiles:
if tile.colliderect(self.rect):
if self.x_vel >= 1:
self.rect.right = tile.left
elif self.x_vel <= -1:
self.rect.left = tile.right
def yCollision(self):
for tile in tiles:
if tile.colliderect(self.rect):
if self.y_vel >= 1:
self.rect.bottom = tile.top
elif self.y_vel <= -1:
self.rect.top = tile.bottom
def Render(self):
self.rect = pygame.draw.rect(screen, (230, 100, 100), (self.x, self.y, self.size, self.size))
self.Gun()
def Alive(self):
if self.health <= 0:
self.alive = False
def GUI(self):
self.empty_health_bar = pygame.draw.rect(screen, (200, 20, 20), (screen.get_width()/4, 10,466, 25))
self.health_bar = pygame.draw.rect(screen, (20, 200, 20), (screen.get_width()/4, 10, self.health*4.66/self.healthboost, 25))
pygame.draw.line(screen, (0, 0, 0), (screen.get_width()/4, 10),(screen.get_width()/4+466, 10), 2)
pygame.draw.line(screen, (0, 0, 0), (screen.get_width()/4, 35),(screen.get_width()/4+466, 35), 2)
pygame.draw.line(screen, (0, 0, 0), (screen.get_width()/4, 10), (screen.get_width()/4, 35), 2)
pygame.draw.line(screen, (0, 0, 0), (screen.get_width()/4+466, 10), (screen.get_width()/4+466, 35), 2)
def Gun(self):
cursor_x, cursor_y = pygame.mouse.get_pos()
dx = cursor_x - (self.x + self.size)
dy = cursor_y - (self.y + self.size)
angle = math.atan2(dy, dx)
self.rotated_gunsurface = pygame.transform.rotate(self.gunsurface, math.degrees(angle * -1))
self.gunrect = self.rotated_gunsurface.get_rect(center = (self.x+self.size/2, self.y+self.size/2))
screen.blit(self.rotated_gunsurface, (self.gunrect.x, self.gunrect.y))
def Shoot(self):
if pygame.key.get_pressed()[pygame.K_e]:
current_time = time.time()
if current_time - self.last_shot_time > self.cooldown:
pop_sound.play()
cursor_x, cursor_y = pygame.mouse.get_pos()
dx = cursor_x - (self.x + self.size/2)
dy = cursor_y - (self.y + self.size/2)
angle = math.atan2(dy, dx)
self.projectiles.append(Projectile(self.x+self.size/2, self.y+self.size/2, angle))
self.last_shot_time = current_time
self.cooldown = 0.1
def Movement(self):
global tiley_offset, tilex_offset
keys = pygame.key.get_pressed()
if self.x >= screen.get_width()-100-self.size: # Move to the RIGHT
if keys[pygame.K_d]:
tilex_offset -= self.speed
if keys[pygame.K_a]:
self.x_vel = -self.speed
if not self.y <= 100:
if keys[pygame.K_w]:
self.y_vel = -self.speed
else:
if keys[pygame.K_w]:
tiley_offset += self.speed
if not self.y >= screen.get_height()-100-self.size:
if keys[pygame.K_s]:
self.y_vel = self.speed
else:
if keys[pygame.K_s]:
tiley_offset -= self.speed
elif self.x <= 100: # Move to the LEFT
if keys[pygame.K_a]:
tilex_offset += self.speed
if keys[pygame.K_d]:
self.x_vel = self.speed
if not self.y <= 100:
if keys[pygame.K_w]:
self.y_vel = -self.speed
else:
if keys[pygame.K_w]:
tiley_offset += self.speed
if not self.y >= screen.get_height()-100-self.size:
if keys[pygame.K_s]:
self.y_vel = self.speed
else:
if keys[pygame.K_s]:
tiley_offset -= self.speed
elif self.y >= screen.get_height()-100-self.size: # Move DOWN
if keys[pygame.K_s]:
tiley_offset -= self.speed
if keys[pygame.K_w]:
self.y_vel = -self.speed
if keys[pygame.K_a]:
self.x_vel =- self.speed
if keys[pygame.K_d]:
self.x_vel = self.speed
elif self.y <= 100: # Move UP
if keys[pygame.K_w]:
tiley_offset += self.speed
if keys[pygame.K_s]:
self.y_vel = self.speed
if keys[pygame.K_a]:
self.x_vel = -self.speed
if keys[pygame.K_d]:
self.x_vel = self.speed
else: # Default Movement
if keys[pygame.K_w]:
self.y_vel = -self.speed
if keys[pygame.K_s]:
self.y_vel = self.speed
if keys[pygame.K_a]:
self.x_vel = -self.speed
if keys[pygame.K_d]:
self.x_vel = self.speed
self.x += self.x_vel
self.xCollision()
self.y += self.y_vel
self.yCollision()
self.y_vel = 0
self.x_vel = 0
class Projectile:
def __init__(self, x, y, angle):
self.x = x
self.y = y
self.angle = angle
self.speed = 8
self.hitbox = pygame.Rect(self.x, self.y, 5,5)
def Move(self):
self.x += math.cos(self.angle) * self.speed
self.y += math.sin(self.angle) * self.speed
def Render(self):
self.hitbox = pygame.draw.circle(screen, (255, 255, 0), (int(self.x), int(self.y)), 7)
class Enemy:
def __init__(self, health, main_speed, tag, size, player, x, y):
self.health = health
self.main_speed = 3
self.tag = tag
self.size = size
self.player = player
self.speed = 3
self.x = x
self.y = y
self.alive = True
def Destroy(self):
self.alive = False
def Spawning(self):
self.hitbox = pygame.draw.rect(screen, (100, 240, 100), (self.x + tilex_offset, self.y + tiley_offset, self.size, self.size))
def Movement(self):
dx = self.player.x - self.x
dy = self.player.y - self.y
angle = math.atan2(dy - tiley_offset, dx - tilex_offset)
self.x += self.speed * math.cos(angle)
self.y += self.speed * math.sin(angle)
def main():
player = Player(100, 3, screen.get_width()/2-50, screen.get_height()/2-50, 50, 1, tiles)
enemies = []
def Spawn_enemies(num_enemies, player):
for i in range(num_enemies):
x, y = random.choice(enemy_spawns)
enemy = Enemy(1, 1, i, 25, player, x*tile_size, y*tile_size)
enemies.append(enemy)
print(x, y)
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
# Main Loop
screen.fill((100, 100, 200))
# usage
spawn_enemies_chance = random.randint(0, 200)
number_of_enemies = len(enemies)
if spawn_enemies_chance == 1 and number_of_enemies <= 4:
Spawn_enemies(1,player)
Build_Level()
# enemy
for enemy in enemies:
if enemy.alive:
enemy.Movement()
enemy.Spawning()
for projectile in player.projectiles:
if enemy.hitbox.colliderect(projectile.hitbox):
enemy.health -= 1
pop_sound.play()
if enemy.health <= 0:
enemy.alive = False
enemies.remove(enemy)
player.projectiles.remove(projectile)
keys = pygame.key.get_pressed()
if keys[pygame.K_LSHIFT]: # Slow things down by 3 times
player.is_slowed = True
for enemy in enemies:
enemy.speed = enemy.main_speed / 3
for projectile in player.projectiles:
projectile.speed = 2.6
player.speed = 1
player.cooldown = 1.5
spawn_enemies_chance = random.randint(0, 1500)
else:
player.is_slowed = False
for enemy in enemies:
enemy.speed = enemy.main_speed
for projectile in player.projectiles:
projectile.speed = 8
player.speed = 3
player.cooldown = 0.5
spawn_enemies_chance = random.randint(0, 500)
# Get Hurt
for enemy in enemies:
if enemy.hitbox.colliderect(player):
player.health -= 10
enemies.remove(enemy)
# Projectiles
for i, projectile in enumerate(player.projectiles):
projectile.Move()
projectile.Render()
if projectile.x < 0 or projectile.x > screen.get_width() or projectile.y < 0 or projectile.y > screen.get_height():
player.projectiles.pop(i)
# player
player.Alive()
player.Movement()
player.Shoot()
player.Render()
# Renders the UI ontop of everything
player.GUI()
pygame.display.update()
clock.tick(fps)
pygame.quit()
# DO NOT DISTURB!
if __name__ == "__main__":
main()
I honestly don't know why its not working but i think i know why its lagging.
It has to check for collision with every tile every single frame which causes some lag if you have a big map i belive, that's just my thought tho.
The actual problem is not the collision detection, but that Build_Level is called in the application loop. Therefore the tiles and enemy_spawns list contain more and more elements over time and your code gets slower and slower. To solve your problem, separate the function into two functions, build_level and draw_level. Call build_level before the application loop, but draw_level in the application loop:
def build_level():
for tiley, rows in enumerate(level):
for tilex, tile in enumerate(rows):
if tile == '1':
tile_rect = pygame.Rect(tilex*tile_size+tilex_offset, tiley*tile_size+tiley_offset, tile_size, tile_size)
tiles.append(tile_rect)
elif tile == '0':
pass
elif tile == 'E':
enemy_spawns.append([tilex, tiley])
elif tile == 'S':
pass
elif tile == 'R':
pass
else:
print("Wrong Map Input")
def draw_level():
for tiley, rows in enumerate(level):
for tilex, tile in enumerate(rows):
color = None
if tile == '1':
color = (100, 100, 100)
elif tile == 'S':
color = (50, 255, 100)
elif tile == 'R':
color = (255, 50, 50)
if color:
pygame.draw.rect(screen, color, (tilex*tile_size+tilex_offset, tiley*tile_size+tiley_offset, tile_size, tile_size))
def main():
# [...]
build_level()
running = True
while running:
# [...]
draw_level()

Object to shoot a projectile

I'm trying to make my tanks shoot, and I did all the code I think I should have done but I don't know why the tanks aren't shooting anything.
import pygame, assetloader
from pygame.locals import *
import random, time, math
import pygame
GRAD = math.pi/180
blue = (0, 0, 255)
wallRects = []
bullets = []
maze = [[] for i in range(25)]
assetloader.set_asset_path("assets/")
I defined the Bullet Class here:
def calculate_dir_with_angle(angle):
direction = [0, 0]
if (angle > 0 and angle < 180) or (angle > -360 and angle < -180):
direction[0] = -1
elif (angle > -180 and angle < 0) or (angle > 180 and angle < 360):
direction[0] = 1
elif (angle > -90 and angle < 90) or (angle > 270 and anlge < 360):
direction[1] = -1
elif (angle > 90 and angle < 270) or (angle > -270 and angle < -90):
direction[1] = 1
return direction
class Bullet:
def __init__(self, pos, r, angle):
self.x = pos[0]
self.y = pos[1]
self.r = r
self.counter = 50
direction = calculate_dir_with_angle(angle)
self.vel = [direction[0] * 2, direction[1] * 2]
def draw(self, screen):
self.x = int(self.x)
self.y = int(self.y)
pygame.draw.circle(screen, (25, 25, 25), (self.x, self.y), (self.r))
def move(self):
self.x += self.vel[0]
self.y += self.vel[1]
self.rect = pygame.Rect(self.x-self.r, self.y - self.r, 2 * self.r, 2 * self.r)
for wr in wallRects:
if self.rect.centery >= wr.top and self.rect.centery <= wr.bottom:
if self.rect.left <= wr.right and self.rect.left > wr.left:
self.vel[0] = -self.vel[0]
self.x = wr.right + self.r + 1
self.rect.x = wr.right + 1
elif self.rect.right >= wr.left and self.rect.right < wr.right:
self.vel[0] = -self.vel[0]
self.x = wr.left + self.r - 1
self.rect.x = wr.left - 2 * self.r - 1
if self.rect.centerx >= wr.left and self.rect.centerx <= wr.right:
if self.rect.top <= wr.bottom and self.rect.top > wr.top:
self.vel[1] = -self.vel[1]
self.y = wr.bottom + self.r + 1
self.rect.y = wr.bottom + 1
elif self.rect.bottom >= wr.top and self.rect.bottom < wr.bottom:
self.vel[1] = -self.vel[1]
self.y = wr.top - self.r - 1
self.rect.y = wr.top - 2 * self.r - 1
if self.counter > 0:
self.counter -= 1
def generateRandomPosition():
row = random.randint(1, 23)
col = random.randint(1, 23)
while maze[row][col-1] != 0 or maze[row][col] != 0 or maze[row][col+1] != 0:
row = random.randint(1, 23)
col = random.randint(1, 23)
return row, col
Player 1:
class Player(pygame.sprite.Sprite):
def __init__(self, x, y, pos):
pygame.sprite.Sprite.__init__(self)
self.image, self.rect = assetloader.load_image("Tank.png", -1)
self.rect.x = x
self.rect.y = y
self.rect.clamp_ip(screen.get_rect())
self.rows = pos[0]
self.cols = pos[1]
self.x = self.cols * gsize
self.y = self.rows * gsize
self.orig_image, self.orig_rect = assetloader.load_image("Tank.png", -1)
self.orig_rect.x = self.x
self.orig_rect.y = self.y
self.orig_gun_pos = self.orig_rect.midtop
self.ammo = 5
def checkCollisions(self):
for b in bullets:
if b.counter <= 0:
if b.rect.colliderect(self.orig_rect):
self.dead = True
def calculate_gun_pos(self):
self.orig_gun_pos = self.orig_rect.midtop
new_y = self.orig_gun_pos[1] - self.orig_rect.centery
new_x = self.orig_gun_pos[0] - self.orig_rect.centerx
rads = self.dir * GRAD
gun_x = (new_y * math.sin(rads)) + (new_x * math.cos(rads)) + (self.orig_rect.centerx)
gun_y = (new_y * math.cos(rads)) - (new_x * math.sin(rads)) + (self.orig_rect.centery)
self.gun_pos = (gun_x, gun_y)
def shoot(self):
if self.ammo > 0:
self.calculate_gun_pos()
b = Bullet(self.gun_pos, 3, self.dir)
bullets.append(b)
self.ammo -= 1
def draw(self, screen):
image = pygame.transform.rotate(self.image, self.dir)
screen.blit(image, self.rect)
def update(self):
oldCenter = self.rect.center
self.rect = self.image.get_rect()
self.rect.center = oldCenter
screen_rect = screen.get_rect()
keys = pygame.key.get_pressed()
if keys[K_m]:
p.shoot()
if not screen_rect.contains(self.rect):
self.rect.clamp_ip(screen_rect)
Calling the functions:
size = width, height = 500, 400
gsize = 25
start_x, start_y = 0, 0
bgColor = 255, 255, 255
pygame.init()
screen = pygame.display.set_mode(size)#, pygame.FULLSCREEN)
pygame.display.set_caption("Sample Sprite")
clock = pygame.time.Clock()
p = Player(width/2, height/4, (3,4))
coll_font = pygame.font.Font(None, 30)
going = True
while going:
clock.tick(60)
for event in pygame.event.get():
if event.type == QUIT:
going = False
elif event.type == KEYDOWN:
if event.key == K_ESCAPE:
going = False
elif event.type == KEYDOWN:
if event.key == K_m:
p.shoot()
for b in bullets:
b.move()
p.update()
screen.fill(bgColor)
p.draw(screen)
pygame.display.flip()
pygame.quit()
How would I call the bullet to actually appear and fire because I have the Bullet class which gets called within the Player class in def shoot(self) so does anyone have an idea why the bullets aren't appearing?
I usually add bullets in this way: I pass the group that contains all sprites and the bullet group to the player instance and add new bullets to these group in the player's handle_event method.
import pygame as pg
from pygame.math import Vector2
pg.init()
screen = pg.display.set_mode((640, 480))
screen_rect = screen.get_rect()
FONT = pg.font.Font(None, 24)
BG_COLOR = pg.Color('gray12')
BULLET_IMAGE = pg.Surface((20, 11), pg.SRCALPHA)
pg.draw.polygon(
BULLET_IMAGE, pg.Color('aquamarine1'), [(0, 0), (20, 5), (0, 11)])
PLAYER_IMAGE = pg.Surface((50, 30), pg.SRCALPHA)
pg.draw.polygon(
PLAYER_IMAGE, pg.Color('dodgerblue1'), [(0, 0), (50, 15), (0, 30)])
class Player(pg.sprite.Sprite):
def __init__(self, pos, all_sprites, bullet_group):
super().__init__()
self.image = PLAYER_IMAGE
self.orig_image = self.image # Needed to preserve image quality.
self.rect = self.image.get_rect(center=(pos))
self.pos = Vector2(pos)
self.vel = Vector2(1, 0)
self.angle = 0
self.angle_speed = 0
self.all_sprites = all_sprites
self.bullet_group = bullet_group
def handle_event(self, event):
if event.type == pg.MOUSEBUTTONDOWN:
# Left button fires a bullet from cannon center with
# current angle. Add the bullet to the bullet_group.
if event.button == 1:
bullet = Bullet(self.pos, self.angle)
self.bullet_group.add(bullet)
self.all_sprites.add(bullet)
elif event.type == pg.KEYDOWN:
# Rotate self by setting the .angle_speed.
if event.key in (pg.K_a, pg.K_LEFT):
self.angle_speed = -3
elif event.key in (pg.K_d, pg.K_RIGHT):
self.angle_speed = 3
elif event.type == pg.KEYUP:
if event.key in (pg.K_a, pg.K_LEFT):
self.angle_speed = 0
elif event.key in (pg.K_d, pg.K_RIGHT):
self.angle_speed = 0
def update(self):
self.pos += self.vel
self.rect.center = self.pos
if self.angle_speed != 0:
self.rotate()
def rotate(self):
# Update the angle and the velocity vector.
self.angle += self.angle_speed
self.vel.rotate_ip(self.angle_speed)
# Rotate the image and get a new rect with the previous center.
self.image = pg.transform.rotozoom(self.orig_image, -self.angle, 1)
self.rect = self.image.get_rect(center=self.rect.center)
class Bullet(pg.sprite.Sprite):
def __init__(self, pos, angle):
super().__init__()
self.image = pg.transform.rotate(BULLET_IMAGE, -angle)
self.rect = self.image.get_rect(center=pos)
# To apply an offset (40 pixels) to the start position,
# create another vector and rotate it as well.
offset = Vector2(40, 0).rotate(angle)
# Add the offset vector to the position vector (the center).
self.pos = Vector2(pos) + offset
# Rotate the start velocity vector (9, 0) by the angle.
self.vel = Vector2(9, 0).rotate(angle)
def update(self):
# Add the velocity to the pos to move the sprite.
self.pos += self.vel
self.rect.center = self.pos # Update the rect as well.
# Remove bullets outside of the screen area.
if not screen_rect.contains(self.rect):
self.kill()
def main():
clock = pg.time.Clock()
all_sprites = pg.sprite.Group()
# Bullets will be added to this group.
bullet_group = pg.sprite.Group()
# Pass the bullet group to the player.
player = Player((300, 200), all_sprites, bullet_group)
all_sprites.add(player)
playing = True
while playing:
for event in pg.event.get():
if event.type == pg.QUIT:
playing = False
# Pass events to the player instance.
player.handle_event(event)
all_sprites.update()
screen.fill(BG_COLOR)
all_sprites.draw(screen)
pg.display.update()
clock.tick(30)
if __name__ == '__main__':
main()
pg.quit()

IndexError: list index out of range, snake game

'''
Created on 13.3.2016
worm game
#author: Hai
'''
import pygame
import random
from pygame import * ##
class Worm:
def __init__(self, surface):
self.surface = surface
self.x = surface.get_width() / 2
self.y = surface.get_height() / 2
self.length = 1
self.grow_to = 50
self.vx = 0
self.vy = -1
self.body = []
self.crashed = False
self.color = 255, 255, 0
def key_event(self, event):
""" Handle keyboard events that affect the worm. """
if event.key == pygame.K_UP and self.vy != 1:
self.vx = 0
self.vy = -1
elif event.key == pygame.K_RIGHT and self.vx != -1:
self.vx = 1
self.vy = 0
elif event.key == pygame.K_DOWN and self.vy != -1:
self.vx = 0
self.vy = 1
elif event.key == pygame.K_LEFT and self.vx != 1:
self.vx = -1
self.vy = 0
def move(self):
""" Moving worm """
self.x += self.vx # add vx to x
self.y += self.vy
if (self.x, self.y) in self.body:
self.crashed = True
self.body.insert(0, (self.x, self.y))
# Changes worm to right size so it is grow_to
if self.grow_to > self.length:
self.length += 1
# If body is longer than length then pop
if len(self.body) > self.length:
self.body.pop()
"""
def draw(self):
self.surface.set_at((int(self.x), int(self.y)), (255, 255, 255))
self.surface.set_at((int(self.last[0]),int(self.last[1])), (0,0,0))
"""
def position(self):
return self.x, self.y
def eat(self):
self.grow_to += 25
def draw(self):
x, y = self.body[0]
self.surface.set_at((int(x), int(y)), self.color)
x, y = self.body[-1]
self.surface.set_at((int(x), int(y)), (0, 0, 0))
# for x, y in self.body:
# self.surface.set_at((int(x), int(y)), self.color)
# pygame.draw.rect(self.surface, self.color, (self.x, self.y, 6, 6), 0)
# worm's head
class Food:
def __init__(self, surface):
self.surface = surface
self.x = random.randint(0, surface.get_width())
self.y = random.randint(0, surface.get_height())
self.color = 255,255,255
def draw(self):
self.surface.set_at((int(self.x),int(self.y)), self.color)
pygame.draw.rect(self.surface, self.color, (self.x, self.y, 6, 6), 0)
def position(self):
return self.x, self.y
""" Check if worm have eaten this food """
def check(self, x, y):
if x < self.x or x > self.x + 6:
return False
elif y < self.y or y > self.y + 6:
return False
else:
return True
def erase(self):
pygame.draw.rect(self.surface, (0,0,0), (int(self.x), int(self.y), 6, 6), 0)
w = h = 500
screen = pygame.display.set_mode((w, h))
clock = pygame.time.Clock()
pygame.mixer.init()
chomp = pygame.mixer.Sound("bow.wav")
score = 0
worm = Worm(screen) ###
food = Food(screen)
running = True
while running:
# screen.fill((0, 0, 0)) optimized in worm draw()
worm.draw()
food.draw()
worm.move()
if worm.crashed or worm.x <= 0 or worm.x >= w-1 or worm.y <= 0 or worm.y >= h-1:
print("U lose")
running = False
elif food.check(worm.x, worm.y):
worm.eat()
food.erase()
chomp.play()
score += 1
print("Score is: %d" % score)
food = Food(screen)
for event in pygame.event.get():
if event.type == pygame.QUIT: # Pressed X
running = False
elif event.type == pygame.KEYDOWN: # When pressing keyboard
worm.key_event(event)
pygame.display.flip()
clock.tick(100)
hello i am getting error
x, y = self.body[0]
IndexError: list index out of range
and i am doing this tutorial:
https://lorenzod8n.wordpress.com/2008/03/01/pygame-tutorial-9-first-improvements-to-the-game/
I am very new to python, plz help me
The problem is that in your class's __init__ function, you define self.body = []. This means that the list contains 0 items.
Later in your code, you reference self.body[0] and self.body[1], which are the first and second items in the list. Since these do not exist, an error is raised. To fix this, you need to initialize self.body with two items.
Based on the order of the operations you are doing, your body list is actually still empty. Follow the logic of your code, and you will see.
You start by instantiating your worm here:
worm = Worm(screen) ###
So, if you look at the __init__ of Worm, you are setting self.body to an empty list [].
If you follow all the code that happens from then until you actually call:
worm.draw()
You are never actually inserting anything on to your body list. So, when you try to access your body list inside your draw method:
error x, y = self.body[0]
You are definitely going to get an index out of range error, since there is nothing to access.
To rectify this you need to either provide a default like:
# arbitrary data
self.body = [0, 0]
Or, determine in your draw method how to handle empty lists using some condition like:
if self.body:
# do things
In your Worm's __init__ function you can set self.body[] to self.body[(0, 0)], this works. The error is raised because you defined an empty list at the beginning and later you tried to get an item from the list by passing an index (self.body[0]). But because the list is empty, Python cannot get the asked value.
Hope this helps!

Python/Pygame Trouble with Game loop/Getting code to run

For the past few days I've been working on this code for pong and I've almost got it running. Everything works up to the movement of the objects. The screen just freezes when the pygame window opens. There seems to be something wrong in my main() but I am still fairly new to python/pygame and am lost as to what is wrong.
import pygame, sys
pygame.init()
SCR_WID, SCR_HEI = 640, 480
class Player():
def __init__(self):
self.x, self.y = 16, SCR_HEI/2
self.x1, self.y1 = SCR_WID-16, SCR_HEI/2
self.speed = 3
self.padWid, self.padHei = 8, 64
self.score = 0
self.scoreFont = pygame.font.Font("imagine_font.ttf", 64)
def scoring(self):
scoreBlit = self.scoreFont.render(str(self.score), 1, (0,0,0))
screen.blit(scoreBlit, (32, 16))
if self.score == 10:
print ("player 1 wins!")
exit()
def scoring1(self):
scoreBlit = self.scoreFont.render(str(self.score), 1, (0,0,0))
screen.blit(scoreBlit, (SCR_HEI+92, 16))
if self.score == 10:
print ("Player 2 wins!")
exit()
def movement(self):
keys = pygame.key.get_pressed()
if keys[pygame.K_w]:
self.y -= self.speed
elif keys[pygame.K_s]:
self.y += self.speed
if self.y <= 0:
self.y = 0
elif self.y >= SCR_HEI-64:
self.y = SCR_HEI-64
keys1 = pygame.key.get_pressed()
if keys1[pygame.K_UP]:
self.y1 -= self.speed
elif keys1[pygame.K_DOWN]:
self.y1 += self.speed
if self.y1 <= 0:
self.y1 = 0
elif self.y >= SCR_HEI-64:
self.y1 = SCR_HEI-64
def draw(self):
pygame.draw.rect(screen, (0,0,0), (self.x, self.y, self.padWid, self.padHei))
pygame.draw.rect(screen, (0,0,0), (self.x1, self.y1, self.padWid, self.padHei))
class Ball():
def __init__(self):
self.x, self.y = SCR_WID/2, SCR_HEI/2
self.x1, self.y1 = SCR_WID/2, SCR_HEI/2
self.speed_x = -3
self.speed_y = 3
self.size = 8
def movement(self):
self.x += self.speed_x
self.y += self.speed_y
if self.y <= 0:
self.speed_y *= -1
elif self.y >= SCR_HEI-self.size:
self.speed_y *= -1
if self.x <= 0:
self.__init__()
enemy.score += 1
elif self.x >= SCR_WID-self.size:
self.__init__()
self.speed_x = 3
player.score += 1
for n in range(-self.size, player.padHei):
if self.y == player.y + n:
if self.x <= player.x + player.padWid:
self.speed_x *= -1
break
n += 1
self.x1 += self.speed_x
self.y1 += self.speed_y
if self.y1 <= 0:
self.speed_y *= -1
elif self.y1 >= SCR_HEI-self.size:
self.speed_y *= -1
if self.x1 <= 0:
self.__init__()
enemy.score += 1
elif self.x1 >= SCR_WID-self.size:
self.__init__()
self.speed_x = 3
player.score += 1
for n in range(-self.size, enemy.padHei):
if self.y1 == enemy.y1 + n:
if self.x1 >= enemy.x1 - enemy.padWid:
self.speed_x *= -1
break
n += 1
def draw(self):
pygame.draw.rect(screen, (112,138,144), (self.x, self.y, 8, 8))
SCR_WID, SCR_HEI = 640, 480
screen = pygame.display.set_mode((SCR_WID, SCR_HEI))
player = Player()
ball = Ball()
enemy = Player()
def main():
running = True
while running == True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
print ("Game exited by user")
exit()
else:
running = False
pygame.font.init()
clock = pygame.time.Clock()
FPS = 60
backgroundimage = pygame.image.load("background.png")
pygame.display.set_caption("Justin's pong")
ball.movement()
player.movement()
enemy.movement()
position = (0,0)
screen.fill((0, 0, 0))
screen.blit(backgroundimage, position)
ball.draw()
player.draw()
player.scoring()
enemy.draw()
enemy.scoring1()
pygame.display.flip()
clock.tick(FPS)
main()
The problem is this code:
running = True
while running == True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
print ("Game exited by user")
exit()
else:
running = False
You are correctly getting the events, but if there aren't any events (as there aren't in the beginning), you will run forever, checking for events.
I assume you want the rest of your code to run in the while loop as well, so you should indent it.

Pygame, keep jumping and glitching through the "ground"

My character won't jump properly, he keeps glitching through the ground. If i hold key up, my character won't stop going higher. Do you have some ideas for how I could fix it?
import pygame,sys
from pygame.locals import *
pygame.init()
screen = pygame.display.set_mode((1200, 800))
screen.fill((0,0,0))
pygame.display.set_caption('Jump and Run')
BLACK = (0,0,0)
WHITE = (250, 250,250)
RED = (250, 0, 0)
BLUE = (0,0,250)
direction = 'right'
way = 0
jump_high = 0
class Hero():
def __init__(self, x, y):
self.x = x
self.y = y
self.image = pygame.image.load('hero.bmp')
self.groundcontact = True
self.vy = 0
alive = True
def check_pos(self):
if self.y >= 400:
self.groundcontact = True
elif self.y <= 400:
self.groundcontact = False
def load_picture(self,surface):
surface.blit(self.image,(self.x, self.y))
def check_input(self):
key = pygame.key.get_pressed()
if key[pygame.K_RIGHT]:
self.x += 10
elif key[pygame.K_LEFT]:
self.x -= 10
elif key[pygame.K_UP]:
self.y -= 50
if not self.groundcontact:
self.vy += 1 #max(min(2,200), -200)
#self.y += self.vy
print "not self.groundcontact"
else:
self.vy = 0
#self.y += self.vy
self.y += self.vy
class Monster():
def __init__(self, x, y):
self.x = x
self.y = y
self.image = pygame.image.load('monster.bmp')
self.collision = False
self.alive = True
def load_picture(self,surface):
surface.blit(self.image,(self.x, self.y))
def walk(self):
global direction
global way
if direction == "right":
self.x += 4
way += 1
if way == 100:
direction = "left"
elif direction == "left":
self.x -= 4
way -= 1
if way == 0:
direction = "right"
monster2 = Monster( 200, 333)
monster1 = Monster(400, 450)
hero = Hero(0, 400)
clock = pygame.time.Clock()
pygame.draw.rect(screen, WHITE,(0,500, 1200, 50))
while True:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
hero.check_pos()
monster1.walk()
monster2.walk()
hero.check_input()
screen.fill(BLACK)
hero.load_picture(screen)
monster1.load_picture(screen)
monster2.load_picture(screen)
pygame.draw.rect(screen, WHITE,(0,500, 1200, 50))
pygame.display.update()
clock.tick(40)
Regarding my comment above, changing the Hero class to somthing like this:
JUMP_POWER = 10
class Hero():
...
def check_input(self):
key = pygame.key.get_pressed()
...
elif key[pygame.K_UP]:
if self.groundcontact:
self.vy -= JUMP_SPEED

Categories