I am trying to add in random drops from enemy deaths to a game I am making in Python and wondering how to implement it. the drops I am wanting to add currently are shield and health, with shield having a lower drop chance. The main code for Drops are here:
import pygame
class HealthDrop(pygame.sprite.Sprite):
def __init__(self, x, y):
self.image = pygame.image.load('images/Sprites/health.png')
self.rect = self.image.get_rect()
self.rect.x = x
self.rect.y = y
self.on_ground = False
self.gravity = 0.5
def update(self):
def render(self, surface):
surface.blit(self.image, self.rect)
class ShieldDrop(pygame.sprite.Sprite):
def __init__(self, x, y):
self.image = pygame.image.load('images/Sprites/shield.png')
self.rect = self.image.get_rect()
self.rect.x = x
self.rect.y = y
self.on_ground = False
self.gravity = 0.5
def update(self):
def render(self, surface):
surface.blit(self.image, self.rect)
Then the code for the main file is here:
import pygame, sys
import random
import pygame.mixer
import Funk
from time import sleep
from player import *
from zombie import *
from level import *
from bullet import *
from constants import *
from Drops import *
import menu as dm
class Game():
def __init__(self):
pygame.init()
pygame.mixer.init()
#pygame.mixer.music.load('sounds/menugame.ogg')
#pygame.mixer.music.play(-1)
# A few variables
self.gravity = .50
self.ground = pygame.Rect(0, 640, 1280, 80)
self.red = (255, 0, 0)
self.darkred = (200, 0, 0)
self.darkblue = (0, 0, 200)
self.darkgreen = (0, 200, 0)
self.gameover = pygame.image.load('images/gameover.png')
self.victory = pygame.image.load('images/victory.png')
# Bullets
self.bullets = []
# Screen
size = (1280, 720)
self.screen = pygame.display.set_mode(size)
pygame.display.set_caption('Moon Survival!')
# Moon / Background
self.moon = Background()
self.text1 = pygame.image.load('images/TextSlides/Text1.jpg')
self.text2 = pygame.image.load('images/TextSlides/Text2.jpg')
# Zombies
self.zombies = []
for i in range(15):
self.zombies.append( Zombie(random.randint(0,1280), random.randint(0,720)) )
self.zombieskilled = 0
# Player
self.player = Player(25, 320, self.gravity)
# Font for text
self.font = pygame.font.SysFont(None, 72)
# game over
self.gameover_text = self.font.render("The Aliens Are Too Good", -1, (255, 0, 0))
self.gameover_rect = self.gameover_text.get_rect(center=self.screen.get_rect().center)
# game state
self.game_state = STATE_INGAME
def run(self):
clock = pygame.time.Clock()
# "state machine"
RUNNING = True
PAUSED = False
GAME_OVER = False
# Game loop
while RUNNING:
# (all) Events
if self.game_state == STATE_INGAME:
for event in pygame.event.get():
if event.type == pygame.QUIT:
RUNNING = False
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_s:
self.bullets.append(Bullet(self.player.rect.x + 30, self.player.rect.y + 30, self.player.direction))
if event.key == pygame.K_ESCAPE:
RUNNING = False
elif event.key == pygame.K_p:
# set state to paused
self.game_state = STATE_PAUSED
# Player/Zomies events
self.player.handle_events(event)
# (all) Movements / Updates
self.player_move()
self.player.update()
for z in self.zombies:
self.zombie_move(z)
z.update(self.screen.get_rect())
for b in self.bullets:
b.update()
for tile in self.moon.get_surrounding_blocks(b):
if tile is not None:
if pygame.sprite.collide_rect(b, tile):
# Destroy block
x = tile.rect.x / tile.rect.width
y = tile.rect.y / tile.rect.height
self.moon.levelStructure[x][y] = None
self.bullets.remove(b)
# (all) Display updating
self.moon.render(self.screen)
for z in self.zombies:
z.render(self.screen)
for b in self.bullets:
b.render(self.screen)
self.player.render(self.screen)
Funk.text_to_screen(self.screen, 'Level 1', 5, 675)
Funk.text_to_screen(self.screen, 'Health: {0}'.format(self.player.health), 5, 0)
Funk.text_to_screen(self.screen, 'Score: {0}'.format(self.player.score), 400, 0)
Funk.text_to_screen(self.screen, 'Time: {0}'.format(self.player.alivetime), 750, 0)
Funk.text_to_screen(self.screen, 'Kills: {0}'.format(self.zombieskilled), 5, 50)
Funk.text_to_screen(self.screen, 'Lives: {0}'.format(self.player.lives), 300, 50)
elif self.game_state == STATE_PAUSED:
# (all) Display updating
if self.game_state == STATE_INGAME:
if event.type == pygame.QUIT:
RUNNING = False
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
RUNNING = False
choose = dm.dumbmenu(self.screen, [
'Resume Game',
'Menu',
'Quit Game'], 200, 200,'orecrusherexpanded',100,0.75,self.darkred,self.red)
if choose == 0:
print "You choose 'Start Game'."
# set state to ingame
self.game_state = STATE_INGAME
elif choose == 1:
print "You choose 'Controls'."
if choose == 2:
print "You choose 'Quit Game'."
pygame.quit()
sys.exit()
#for event in pygame.event.get():
self.moon.render(self.screen)
for z in self.zombies:
z.render(self.screen)
for b in self.bullets:
b.render(self.screen)
self.player.render(self.screen)
Funk.text_to_screen(self.screen, 'Level 1', 5, 675)
Funk.text_to_screen(self.screen, 'Health: {0}'.format(self.player.health), 5, 0)
Funk.text_to_screen(self.screen, 'Score: {0}'.format(self.player.score), 400, 0)
Funk.text_to_screen(self.screen, 'Time: {0}'.format(self.player.alivetime), 750, 0)
Funk.text_to_screen(self.screen, 'Kills: {0}'.format(self.zombieskilled), 850, 0)
elif self.game_state == STATE_GAMEOVER:
self.screen.blit(self.gameover, (0, 0))
pygame.display.update()
choose = dm.dumbmenu(self.screen, [
'New Game',
' Menu ',
'Quit Game'], 200, 300,'orecrusherexpanded',100,0.75,self.darkred,self.red)
if choose == 0:
print "You choose 'Start Game'."
# set state to ingame
self.game_state = STATE_INGAME
execfile('MoonSurvival.py')
if choose == 1:
print "You choose 'Start Game'."
execfile('run_game.py')
if choose == 2:
print "You choose 'Start Game'."
pygame.quit()
sys.exit()
pygame.display.update()
# FTP
clock.tick(100)
# --- the end ---
pygame.quit()
def player_move(self):
# add gravity
self.player.do_jump()
# simulate gravity
self.player.on_ground = False
if not self.player.on_ground and not self.player.jumping:
self.player.velY = 4
# Health
for zombie in self.zombies:
if pygame.sprite.collide_rect(self.player, zombie):
self.player.health -= 5
# check if we die
if self.player.health <= 0:
self.player.lives -= 1
self.player.rect.x = 320
self.player.rect.y = 320
self.player.health += 200
if self.player.lives <= 0:
sleep(2)
self.game_state = STATE_GAMEOVER
# move player and check for collision at the same time
self.player.rect.x += self.player.velX
self.check_collision(self.player, self.player.velX, 0)
self.player.rect.y += self.player.velY
self.check_collision(self.player, 0, self.player.velY)
def zombie_move(self, zombie_sprite):
# add gravity
zombie_sprite.do_jump()
# simualte gravity
zombie_sprite.on_ground = False
if not zombie_sprite.on_ground and not zombie_sprite.jumping:
zombie_sprite.velY = 4
# Zombie damage
for zombie in self.zombies:
for b in self.bullets:
if pygame.sprite.collide_rect(b, zombie):
#The same bullet cannot be used to kill
#multiple zombies and as the bullet was
#no longer in Bullet.List error was raised
zombie.health -= 10
self.bullets.remove(b)
if zombie.health <= 0:
self.zombieskilled += 1
self.player.score += 20
self.zombies.remove(zombie)
break
# move zombie and check for collision
zombie_sprite.rect.x += zombie_sprite.velX
self.check_collision(zombie_sprite, zombie_sprite.velX, 0)
zombie_sprite.rect.y += zombie_sprite.velY
self.check_collision(zombie_sprite, 0, zombie_sprite.velY)
def check_collision(self, sprite, x_vel, y_vel):
# for every tile in Background.levelStructure, check for collision
for block in self.moon.get_surrounding_blocks(sprite):
if block is not None:
if pygame.sprite.collide_rect(sprite, block):
# we've collided! now we must move the collided sprite a step back
if x_vel < 0:
sprite.rect.x = block.rect.x + block.rect.w
if type(sprite) is Zombie:
# the sprite is a zombie, let's make it jump
if not sprite.jumping:
sprite.jumping = True
sprite.on_ground = False
if x_vel > 0:
sprite.rect.x = block.rect.x - sprite.rect.w
if type(sprite) is Zombie:
# the sprite is a zombie, let's make it jump
if not sprite.jumping:
sprite.jumping = True
sprite.on_ground = False
if y_vel < 0:
sprite.rect.y = block.rect.y + block.rect.h
if y_vel > 0 and not sprite.on_ground:
sprite.on_ground = True
sprite.rect.y = block.rect.y - sprite.rect.h
#---------------------------------------------------------------------
Game().run()
you need to edit this:
def zombie_move(self, zombie_sprite):
for zombie in self.zombies:
for b in self.bullets:
if pygame.sprite.collide_rect(b, zombie):
zombie.health -= 10
self.bullets.remove(b)
if zombie.health <= 0:
self.zombieskilled += 1
self.player.score += 20
#You need some code here (before removing the zombie)
self.zombies.remove(zombie)
break
I'm sorry I forgot how to do it in Python, but the logic is like that: In place of the comment inside the code add something like HealthDrop.append(x, y) or ShieldDrop.append(x, y) where x and y should be zombie's values (that's why you should do it before removing the zombie).
If you want random chance just add import random then do it like that:
percentage = random.randint(1, 100)
if (percentage >= 1) and (percentage < 10)
healthDrop.append(zombie.x, zombie.y)
else
if (percentage >= 10) and (percentage < 20)
shieldDrop.append(zombie.x, zombie.y)
In this example I set 10% for each "item" to drop (they can't both drop), it randomizes a number from 1 to 100 , if it's a number from 1 to 9 its healthDrop, if it's a number from 10 to 19 its shieldDrop, feel free to experiment with what percentages makes your game balanced
Also don't forget to add collision (I see you already have some code for collision so I guess you know how to do it). The rest of the code should be easy for you to do (like increasing health on pick up etc etc.
I'm sorry I don't remember python really well, but you can use them similar to the bullet class, I hope you have the idea, if there's anything troubling you please tell me and I'll help more :)
Related
Alright, so yes, I get that it is a lot of code I am about to display.
My problem: I am making a zombie shooter game where you are the main character on top of a building and you have to click on zombies as they come in waves. My current problem is whenever multiple zombies overlap on top of each other, I can kill both of them (or as many are overlapping) in one click because technically, all of their hitboxes are colliding.
If this is a bigger problem than sought out to be, I would like someone to just say that.
import pygame
import random
import time
pygame.init()
#Setting Variables
screenW = 1020
screenH = 630
x = 125
y = 164
width = 50
height = 50
velocity = 5
wave = 2
GOLD = (255, 215, 0)
BLACK = (0, 0, 0)
RED = (255, 0, 0)
GREEN = (0, 128, 0)
wallHealth = 0
zombieKilled = 0
class ZombieChars():
def __init__(self):
self.damage = 0
self.vel = 5
self.x_change = random.randrange(2,5)
self.y_change = 1
self.height = 120
self.width = 149
self.color = random.sample(range(250), 4)
self.image = pygame.Surface([self.width, self.height], pygame.HWSURFACE, 32)
self.rect = self.image.get_rect(topleft = (random.randrange(900, 1150), 330))
#pygame.draw.rect(self.image, (self.color), (self.x, self.y, self.width, self.height))
def draw(self):
window.blit(ZombieWalking, self.rect.topleft)
def update(self):
if self.rect.x >= 364:
self.rect.x -= self.x_change
else:
self.rect.x -= 0
def wallHP(self):
global wallHealth
if self.rect.x < 365:
self.damage += 1
if self.damage == 30:
self.damage = 0
wallHealth += 1
def death(self):
global zombieKilled
if event.type == pygame.MOUSEBUTTONDOWN:
gunShot.play()
mouse_pos = event.pos
if self.rect.collidepoint(mouse_pos):
self.rect.x = 5000
self.rect.x -= self.x_change
zombieHit.play()
zombieKilled += 1
print(zombieKilled)
def waveCounter(self):
global wave
print(wave)
if wave == zombieKilled / 2:
wave = 2
#FPS
clock = pygame.time.Clock()
clock.tick(60)
#Screen
window = pygame.display.set_mode((screenW,screenH))
pygame.display.set_caption(("Zombie Shooter"))
#Image Loading
bg = pygame.image.load("bg.jpg")
mainmenu = pygame.image.load("mainmenu.jpg")
ZombieWalking = pygame.image.load("Sprites/AAIdle.png")
#Sound Loading
gunShot = pygame.mixer.Sound('sounds/gunShot.wav')
zombieHit = pygame.mixer.Sound('sounds/zombieHit.wav')
gameMusic = pygame.mixer.music.load('sounds/gameMusic.mp3')
menuMusic = pygame.mixer.music.load('sounds/menuMusic.mp3')
zombies = ZombieChars()
my_list = []
for zombs in range(wave):
my_object = ZombieChars()
my_list.append(my_object)
def text_objects(text, font):
textSurface = font.render(text, True, BLACK)
return textSurface, textSurface.get_rect()
smallText = pygame.font.Font('freesansbold.ttf', 30)
tinyText = pygame.font.Font('freesansbold.ttf', 20)
TextSurf3, TextRect3 = text_objects("Wave: " + str(wave), smallText)
TextRect3.center = ((1020 / 2), (50))
#Main Loop
run = True
mainMenu = True
pygame.mixer.music.play()
global event
while mainMenu == True:
window.blit(mainmenu, (0,0))
pygame.display.flip()
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False #if x is pressed dont run game
mainMenu = False
keys = pygame.key.get_pressed()
if keys[pygame.K_a]:
mainMenu = False #if a is pressed run game
def wallHPBar():
pygame.draw.rect(window, GREEN, (20, 20, 100, 10))
if wallHealth == 0:
pass
if wallHealth == 1:
pygame.draw.rect(window, RED, (20, 20, 25, 10))
if wallHealth == 2:
pygame.draw.rect(window, RED, (20, 20, 50, 10))
if wallHealth == 3:
pygame.draw.rect(window, RED, (20, 20, 75, 10))
if wallHealth >= 4:
pygame.draw.rect(window, RED, (20, 20, 100, 10))
def overlapKill():
if zombieKilled == 1:
print("oh my goodness we going")
if zombieKilled == 2:
print("we 2 ")
while run:
pygame.mixer.music.stop()
window.blit(bg, (0, 0))
window.blit(TextSurf3, TextRect3)
wallHPBar()
pygame.time.delay(25)
for zombie in my_list:
zombie.draw()
zombie.update()
zombie.death()
zombie.wallHP()
zombie.waveCounter()
pygame.display.flip()
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
Thank you.
Remove the event handling from the method death and return a boolean value, that indicates if a zombie was killed:
class ZombieChars():
# [...]
def death(self):
global zombieKilled
mouse_pos = pygame.mouse.get_pos()
if self.rect.collidepoint(mouse_pos):
self.rect.x = 5000
self.rect.x -= self.x_change
zombieHit.play()
zombieKilled += 1
print(zombieKilled)
return True
return False
Do the pygame.MOUSEBUTTONDOWN event handling in the event loop and evaluate if a zombie was killed in a loop. break the loop when a zombie is killed. Thus only one zombie can be get killed on one klick:
while run:
# [...]
pygame.display.flip()
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
if event.type == pygame.MOUSEBUTTONDOWN:
gunShot.play()
for zombie in (reversed):
if zombie.death():
break
for zombie in my_list:
zombie.draw()
zombie.update()
# zombie.death() <--- DELETE
zombie.wallHP()
zombie.waveCounter()
A Zombie object should not be dealing with user-input. Handle the click outside of the zombie, then the outside code gets to decide if the click is "used up".
class ZombieChars():
[ ... ]
def death( self, mouse_position ):
killed = False
global zombieKilled
if self.rect.collidepoint( mouse_position ):
self.rect.x = 5000
self.rect.x -= self.x_change
zombieHit.play()
zombieKilled += 1
print(zombieKilled)
killed = True
return killed
Then in your main loop, stop processing hits once the first is found:
### Main Loop
while not exiting:
for event in pygame.event.get():
if ( event.type == pygame.QUIT ):
exiting = True
elif ( event.type == pygame.MOUSEBUTTONDOWN ):
gunShot.play()
mouse_pos = event.pos
for zombie in my_list:
if ( zombie.death( mouse_pos ) ):
break # stop on first hit
So im new at pygame and coding my first project- a side scrolling shooter. The issue im having is with my bullets: when i press the space key, some of the bullets will show up but there are times when nothing happens, and no bullets spawn when i jump. Not quite sure how to go about fixing this issue- any ideas would be greatly appreciated.
Code is as follows:
import pygame
import math, random, sys, pygame.mixer
from pygame.locals import *
pygame.init()
pygame.mixer.pre_init(44100, -16, 2, 8192)
pygame.mixer.init()
jump = False
jump_offset = 0
jump_height = 250
k = pygame.key.get_pressed()
def events():
for event in pygame.event.get():
if event.type == QUIT or (event.type == KEYDOWN and event.key == K_ESCAPE):
pygame.quit()
sys.exit()
def do_jumping():
global jump_height
global jump
global jump_offset
if jump:
jump_offset += 3
if jump_offset >= jump_height:
jump = False
elif jump_offset > 0 and jump == False:
jump_offset -= 3
#Defining colours
BLACK = ( 0, 0, 0)
WHITE = ( 255, 255, 255)
#Window Settings
w = 1280
h = 720
half_w = w /2
half_h = h /2
AREA = w*h
#Initialising the window
pygame.init()
display = pygame.display.set_mode((w,h)) #Sets the size of the window
pygame.display.set_caption("Cattleman") #Sets the title of the window
Clock = pygame.time.Clock() #clockspeed for the game ie. 60fps
FPS = 600
#pygame.mouse.set_visible(True) #Allows the mouse to be shown in the game window.
background = pygame.image.load("background.png").convert()
backgroundWidth, backgroundHeight = background.get_rect().size
stageWidth = backgroundWidth*2 #sets the area which the player can move in
stagePosX = 0 #Records position of stage as the player moves
startScrollPosX = half_w
circleRadius = 25
circlePosX = circleRadius
playerPosX = circleRadius
playerPosY = 602
playerVelocityX = 0
playersprite = pygame.image.load("player_spriteR2.png").convert_alpha()
playersprite = pygame.transform.scale(playersprite, (130,130))
bullets = []
bulletSprite = pygame.image.load("Bullet1.png").convert_alpha()
bulletSprite = pygame.transform.scale(bulletSprite, (20,10))
#Sounds
#gunSounds = ["pew1.wav", "pew2.wav", "pew3.wav", "pew4.wav"]
#SOUNDS
shot = pygame.mixer.Sound("pew1.wav")
#------------------------MAIN PROGRAM LOOP------------------------#
while True:
events()
do_jumping()
k = pygame.key.get_pressed()
if k[K_RIGHT]:
playerVelocityX = 2 #Moves the player right
playersprite = pygame.image.load("player_spriteR2.png").convert_alpha()
playersprite = pygame.transform.scale(playersprite, (130,130))
if k[K_LEFT]:
playerVelocityX = -2 #Moves the player left
playersprite = pygame.image.load("player_spriteL2.png").convert_alpha()
playersprite = pygame.transform.scale(playersprite, (130,130))
if k[K_UP] and jump == False and jump_offset == 0:
jump = True
if not k[K_RIGHT] and not k[K_LEFT]:
playerVelocityX = 0 #If no input detected, the player does not move
if k[K_SPACE]:
for event in pygame.event.get():
bullets.append([circlePosX-100, playerPosY-20])
shot.play()
playerPosX += playerVelocityX
if playerPosX > stageWidth - circleRadius-25: playerPosX = stageWidth - circleRadius-25 #Checks if the player trie to go past the right boundary
if playerPosX < circleRadius+55:playerPosX = circleRadius+55 #Checks if the player tries to go past the left boundary
if playerPosX < startScrollPosX: circlePosX = playerPosX
elif playerPosX > stageWidth - startScrollPosX: circlePosX = playerPosX - stageWidth + w
else:
circlePosX = startScrollPosX
stagePosX += -playerVelocityX
for b in range(len(bullets)):
bullets[b][0] -= 3
for bullet in bullets[:]:
if bullet[0] < 0:
bullets.remove(bullet)
rel_x = stagePosX % backgroundWidth
display.blit(background,(rel_x - backgroundWidth, 0))
if rel_x < w:
display.blit(background, (rel_x, 0))
for bullet in bullets:
display.blit(bulletSprite, pygame.Rect(bullet[0], bullet[1], 0, 0,))
#pygame.draw.circle(display,WHITE, (int(circlePosX),playerPosY - jump_offset), circleRadius, 0)
display.blit(playersprite, (int(circlePosX-80),playerPosY-100 - jump_offset))
pygame.display.update()
Clock.tick(FPS)
display.fill(BLACK)
I have done this in my code that leaves multiple balls similar like bullets :
class Bullet():
def __init__(self, x, y):
# self.image = pygame.image.load("SingleBullet.png")
self.image = pygame.image.load("ball.png")
self.image = pygame.transform.scale(self.image, (25, 25))
self.rect = self.image.get_rect()
self.rect.centerx = x
self.rect.centery = y
self.is_alive = True
# --------------------
def update(self):
self.rect.y -= 15
if self.rect.y < 0:
self.is_alive = False
# --------------------
def draw(self, screen):
screen.blit(self.image, self.rect.topleft)
for getting keyboard :
def event_handler(self, event):
if event.type == KEYDOWN:
if event.key == K_LEFT:
self.move_x = -5
elif event.key == K_RIGHT:
self.move_x = 5
elif event.key == K_SPACE:
if len(self.shots) < self.max_shots:
self.shots.append(Bullet(self.rect.centerx, self.rect.top))
if event.type == KEYUP:
if event.key in (K_LEFT, K_RIGHT):
self.move_x = 0
I'm having an odd phenomenon where my sound file is playing 8 times, then off, then playing, then off, then playing again.
import sys, pygame, os, time
# Force static position of screen
os.environ['SDL_VIDEO_CENTERED'] = '1'
# to get rid of sound lag
pygame.mixer.pre_init(44100, -16, 8, 2048)
# Runs imported module
pygame.init()
# Constants
UP = 'up'
DOWN = 'down'
BOOSTSP = 12
NORMSP = 8
WIN_W = 920
WIN_H = 570
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
PADDLE_HEIGHT = 440
BALL_WIDTH = BALL_HEIGHT = 20
class Entity(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
class Paddle(Entity):
def __init__(self, x, y):
Entity.__init__(self)
self.x = x
self.y = y
self.speed = 8
self.pWidth = 20
self.score = 0
self.pHeight = PADDLE_HEIGHT
self.paddle = pygame.Surface((self.pWidth, self.pHeight))
self.paddle = self.paddle.convert()
self.lp_moveUP = self.lp_moveDOWN = self.rp_moveUP = self.rp_moveDOWN = False
def update(self, down, up):
# Adjust speed
if up or down or up or down:
if up:
self.y -= self.speed
if down:
self.y += self.speed
# paddle movement
if self.y < 0:
self.y = 0
if self.y > WIN_H - self.pHeight:
self.y = WIN_H - self.pHeight
class Ball(Entity):
def __init__(self, x, y):
Entity.__init__(self)
self.speed = [-5, -5]
self.ball = pygame.Surface((BALL_WIDTH, BALL_HEIGHT))
self.ball = self.ball.convert()
self.rect = pygame.Rect(WIN_W/2, WIN_H/2-(BALL_HEIGHT/2), BALL_WIDTH, BALL_HEIGHT)
def restart(self, lPaddle, rPaddle, screen):
time.sleep(2)
self.rect.y = WIN_H/2-(BALL_HEIGHT/2)
self.rect.x = WIN_W/2
lPaddle.y = (WIN_H/2) - (PADDLE_HEIGHT/2)
rPaddle.y = (WIN_H/2) - (PADDLE_HEIGHT/2)
return True
Notice that in the 'update' method, I am playing a sound if the ball hits the paddle. You can see that I print the return value of the 'playSound' function which is the return value of the play() method.
def update(self, lPaddle, rPaddle, sound, playSound):
# If ball hits the top or bottom
if self.rect.top < 0 or self.rect.top > WIN_H - BALL_HEIGHT:
self.speed[1] = -self.speed[1]
print playSound(sound["bop"], 1)
# If ball hits paddle
if(self.speed[0] < 0):
if (self.rect.left > lPaddle.x + lPaddle.pWidth - 15 and self.rect.left < lPaddle.x + lPaddle.pWidth-10) and (self.rect.top > lPaddle.y and self.rect.top < (lPaddle.y + lPaddle.pHeight)):
self.speed[0] = -self.speed[0]
print playSound(sound["beep"], 1)
else:
if (self.rect.left > rPaddle.x - 15 and self.rect.left < rPaddle.x - 5) and (self.rect.top > rPaddle.y and self.rect.top < (rPaddle.y + rPaddle.pHeight)):
self.speed[0] = -self.speed[0]
print playSound(sound["beep"], 1)
self.rect = self.rect.move(self.speed)
# Returns True for .5 seconds, then False for .5 seconds.
def checkTime(cur, beg):
return (cur - beg) % 1000 < 500
# Takes in string, (x, y) and size. Returns text and rect.
def txtRect(sen, xpos, ypos, size):
phrase = pygame.font.Font(None, size)
phrase = phrase.render(sen, 1, BLACK)
phraseRect = phrase.get_rect()
phraseRect.x = xpos
phraseRect.y = ypos
return phrase, phraseRect
# Loads sound files
def playSound(sound, volume):
sound.set_volume(volume)
return sound.play()
# Loads sound files
def loadSound():
sound = {}
sound["beep"] = pygame.mixer.Sound("sound/beep.ogg")
sound["boom"] = pygame.mixer.Sound("sound/boom.ogg")
sound["bop"] = pygame.mixer.Sound("sound/bop.ogg")
sound["choose"] = pygame.mixer.Sound("sound/choose.ogg")
sound["count"] = pygame.mixer.Sound("sound/count.ogg")
sound["end"] = pygame.mixer.Sound("sound/end.ogg")
sound["music"] = pygame.mixer.Sound("sound/music.ogg")
sound["select"] = pygame.mixer.Sound("sound/select.ogg")
return sound
def main():
size = WIN_W, WIN_H
fps = 60
# Used for count down
countDown = 3
decrement = True
pygame.display.set_caption('Pong')
screen = pygame.display.set_mode(size, pygame.SRCALPHA)
# Create our objects
ball = Ball((WIN_W/2)-(BALL_WIDTH/2), WIN_H/2-(BALL_HEIGHT/2))
lPaddle = Paddle(WIN_W/15, (WIN_H/2)-(PADDLE_HEIGHT/2))
rPaddle = Paddle(WIN_W/1.1, (WIN_H/2)-(PADDLE_HEIGHT/2))
# Create sound objects
sound = loadSound()
clock = pygame.time.Clock()
beg_time = pygame.time.get_ticks()
intro = count = play = outro = True
lp_moveUP = lp_moveDOWN = rp_moveDOWN = rp_moveUP = False
while intro:
# Print background
screen.fill(WHITE)
# Title Text: Pong
text = txtRect("Pong", 0, 0, 200)
text = txtRect("Pong", WIN_W/2-(text[1].width/2), WIN_H/4, 200)
screen.blit(text[0], text[1])
# Blinking Text: Click here to start
text = txtRect("- Click here to start -", 0, 0, 50)
text = txtRect("- Click here to start -", WIN_W/2-(text[1].width/2), WIN_H/1.7, 50)
if checkTime(beg_time, pygame.time.get_ticks()):
screen.blit(text[0], text[1])
# Checks if window exit button pressed
for event in pygame.event.get():
if event.type == pygame.QUIT: sys.exit()
elif event.type == pygame.MOUSEBUTTONDOWN or pygame.key.get_pressed()[pygame.K_RETURN] != 0:
screen.blit(text[0], text[1])
pygame.display.flip()
playSound(sound["select"], .3)
pygame.time.wait(1500)
intro = False
# Limits frames per iteration of while loop
clock.tick(fps)
# Writes to main surface
pygame.display.flip()
# Gameplay
while play:
# Print background
screen.fill(WHITE)
screen.blit(lPaddle.paddle, (lPaddle.x, lPaddle.y))
screen.blit(rPaddle.paddle, (rPaddle.x, rPaddle.y))
screen.blit(ball.ball, ball.rect)
# Print Score
sen = "Player 1 score: " + str(lPaddle.score)
text = txtRect(sen, WIN_W/6.5, WIN_H/57, 40)
screen.blit(text[0], text[1])
sen = "Player 2 score: " + str(rPaddle.score)
text = txtRect(sen, WIN_W - WIN_W/6.5 - text[1].width, WIN_H/57, 40)
screen.blit(text[0], text[1])
# Countdown
if count:
text = txtRect(str(countDown), 0, 0, 75)
text = txtRect(str(countDown), WIN_W/3.5 - (text[1].width/2), WIN_H/4, 75)
screen.blit(text[0], text[1])
text = txtRect(str(countDown), WIN_W/1.4 - (text[1].width/2), WIN_H/4, 75)
screen.blit(text[0], text[1])
# Writes to main surface
pygame.display.flip()
playSound(sound["count"], 1)
time.sleep(1)
countDown -= 1
# bug fix: prevent display of 0.
if countDown == 0:
count = False
# Gameplay
else:
# Checks if window exit button pressed
for event in pygame.event.get():
if event.type == pygame.QUIT: sys.exit()
# Keyboard mechanics
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
pygame.quit()
sys.exit()
if event.key == pygame.K_UP:
rp_moveUP = True
rp_moveDOWN = False
elif event.key == pygame.K_DOWN:
rp_moveUP = False
rp_moveDOWN = True
if event.key == pygame.K_w:
lp_moveUP = True
lp_moveDOWN = False
elif event.key == pygame.K_s:
lp_moveUP = False
lp_moveDOWN = True
elif event.type == pygame.KEYUP:
if event.key == pygame.K_UP:
rp_moveUP = False
elif event.key == pygame.K_DOWN:
rp_moveDOWN = False
if event.key == pygame.K_w:
lp_moveUP = False
elif event.key == pygame.K_s:
lp_moveDOWN = False
lPaddle.update(lp_moveDOWN, lp_moveUP)
rPaddle.update(rp_moveDOWN, rp_moveUP)
ball.update(lPaddle, rPaddle, sound, playSound)
# If ball moves off the screen
if ball.rect.left < 0 - ball.rect.width or ball.rect.left > WIN_W + ball.rect.width:
if ball.rect.left < 0:
rPaddle.score += 1
elif ball.rect.left > WIN_H + ball.rect.width:
lPaddle.score += 1
playSound(sound["end"], 1)
count = ball.restart(lPaddle, rPaddle, screen)
countDown = 3
# Game ends
if lPaddle.score == 3 or rPaddle.score == 3:
playSound(sound["boom"], 1)
break
# Limits frames per iteration of while loop
clock.tick(fps)
# Writes to main surface
pygame.display.flip()
# Gameplay
while outro:
# Print background
screen.fill(WHITE)
# End Text: Player wins
if lPaddle.score == 3 or rPaddle.score == 3:
if lPaddle.score == 3:
sen = "Player 1 Wins!"
else:
sen = "Player 2 Wins!"
text = txtRect(sen, 0, 0, 40)
text = txtRect(sen, WIN_W/2-(text[1].width/2)-130, WIN_H/4, 100)
screen.blit(text[0], text[1])
text = txtRect("- Click here to continue -", 0, 0, 50)
text = txtRect("- Click here to continue -", WIN_W/2-(text[1].width/2), WIN_H/1.7, 50)
# Blinking Text: Click here to start
if checkTime(beg_time, pygame.time.get_ticks()):
screen.blit(text[0], text[1])
# Checks if window exit button pressed
for event in pygame.event.get():
if event.type == pygame.QUIT: sys.exit()
elif event.type == pygame.MOUSEBUTTONDOWN or pygame.key.get_pressed()[pygame.K_RETURN] != 0:
screen.blit(text[0], (WIN_W/2-(text[1].width/2), WIN_H/1.7))
pygame.display.flip()
loadSound("choose", 1)
pygame.time.wait(1500)
outro = False
main()
# Limits frames per iteration of while loop
clock.tick(fps)
# Writes to main surface
pygame.display.flip()
if __name__ == "__main__":
main()
When I play, the intro sounds play and then when the ball bounces off the paddles, the program only plays 8 times with the exact same result every time I play the game. Here is my output. Any help would be much appreciated.
/Library/Frameworks/Python.framework/Versions/2.7/bin/python2.7 /Users/DanielLee/PycharmProjects/newPong/pong7_sound.py
Channel object at 0x1002c42e8
Channel object at 0x1002c42e8
Channel object at 0x1002c42e8
Channel object at 0x1002c42e8
Channel object at 0x1002c42e8
Channel object at 0x1002c42e8
Channel object at 0x1002c42e8
Channel object at 0x1002c42e8
None
None
None
None
Channel object at 0x1002c42e8
None
Channel object at 0x1002c42e8
Channel object at 0x1002c42e8
The reason I believe the sound was playing then not playing had something to do with the channel being used repeatedly. The solution was to set a 'maxtime' for the sound, turning it off and freeing up the channel for later use.
from documentation: play(loops=0, maxtime=0, fade_ms=0)
As can be seen in the documentation for play(), the second argument is 'maxtime' which can be set to ensure that channels will be available.
I don't have a clear understanding of the mechanics of how this works exactly or even if my understanding of the error is valid, so any clarification would be appreciated.
I'm fairly new to programming, game programming especially. I'm trying to make pong using pygame, but have run into a slight issue. Essentially, the ball hits a paddle, stops, and then keeps going once the paddle is out of the way. Obviously I want the ball to bounce back, but I can't figure out why it won't, when I've coded (what I thought was) the appropriate logic for ball-paddle collisions. Here's my code:
# importing stuff
import sys, pygame
from pygame.locals import *
# starting pygame
pygame.init()
# defining basic colours
white = (255, 255, 255)
black = (0, 0, 0)
# set up the clock
clock = pygame.time.Clock()
# text and such
tFont = pygame.font.SysFont("monospace", 15)
# setting window res and setting display
winX, winY = 600, 300
window = pygame.display.set_mode((winX, winY))
# setting the speed for on screen stuff
playSpeed = 5 # player speed (p1 and p2)
# counts points for each player
# 1 2
points = [0, 0]
# tallies number of times FPS is counted and added to toal amount
fpsCount = 0
fpsTotal = 0
class Ball(object):
def __init__(self, speed):
# set default ball position in screen centre
self.ballX = winX / 2
self.ballY = winY / 2
self.ballSpeed = speed
def move(self):
if points[0] > points[1]: # if p1 has more points than p2
self.ballX -= self.ballSpeed # ball goes to p1's side
elif points[0] < points[1]: # only other condition could be p2 having more points
self.ballX += self.ballSpeed # ball goes to p2's side
elif points[0] == points[1]: # if points are equal
self.ballX -= self.ballSpeed # favour player 1 (change later)
pygame.draw.circle(window, black, (self.ballX, self.ballY), 3)
def collide(self, paddle): # unsure if 'paddle' necessary
# if ball hits top of paddle, bounce to top
# if hits bottom, bounce to bottom
# if ball hits midsection, bounce straight (middle could be about 10px?)
if paddle == playerOne:
self.ballX
self.ballX += self.ballSpeed
class Paddle(object):
# set the player number (1/2) and if it's an AI or real player
def __init__(self, player, aiornot):
if player == 1 and aiornot == False:
self.coords = [[40, 130], [40, 160]]
elif player == 2 and aiornot == False:
self.coords = [[560, 130], [560, 160]]
self.movement = 'stop' # sets default movement
def move(self):
if self.movement == 'down' and self.coords[1][1] < 300:
self.moveDown()
elif self.movement == 'up' and self.coords[0][1] > 0:
self.moveUp()
elif self.movement == 'stop':
self.stop()
# draw the paddle in new position
pygame.draw.line(window, black, self.coords[0], self.coords[1], 10)
# movement functions, for direction and such
def moveDown(self):
self.coords[0][1] += playSpeed
self.coords[1][1] += playSpeed
def moveUp(self):
self.coords[0][1] -= playSpeed
self.coords[1][1] -= playSpeed
def stop(self):
self.coords[0][1] = self.coords[0][1]
self.coords[1][1] = self.coords[1][1]
ball = Ball(playSpeed)
playerOne = Paddle(1, False)
playerTwo = Paddle(2, False)
# main loop
while True:
# event handling for exit
for event in pygame.event.get():
if event.type == QUIT:
# print the average FPS
print round(fpsTotal / fpsCount, 2), "fps (avg)"
pygame.quit()
sys.exit()
# setting direction upon arrow key press
elif event.type == KEYDOWN:
if event.key == K_DOWN:
playerOne.movement = 'down'
elif event.key == K_UP:
playerOne.movement = 'up'
elif event.key == K_s:
playerTwo.movement = 'down'
elif event.key == K_w:
playerTwo.movement = 'up'
# when the key is released, stop moving
elif event.type == KEYUP:
if event.key == K_DOWN or event.key == K_UP:
playerOne.movement = 'stop'
elif event.key == K_s or event.key == K_w:
playerTwo.movement = 'stop'
print "player1:", playerOne.coords
print "player2:", playerTwo.coords
# this is a mess... if the balls x coords = the paddles x coords, and the balls y
# coord is somewhere between the start and end point of the paddle, then do the balls
# collision function on the paddle
if ball.ballX >= playerOne.coords[0][0] and ball.ballX <= playerOne.coords[1][0]: # or ball.ballX == 40
if ball.ballY >= playerOne.coords[0][1] and ball.ballY <= playerOne.coords[1][1]:
ball.collide(playerOne)
print ball.ballX, ball.ballY
# fill the window
window.fill(white)
# redraw the bat with new position
playerOne.move()
playerTwo.move()
# redraw the ball with new position
ball.move()
# set FPS to 60
clock.tick(60)
# for working out average FPS
fpsCount += 1
fpsTotal += clock.get_fps()
# set window title
pygame.display.set_caption("Long Pong")
# render FPS to text, display text
text = tFont.render(str(round(clock.get_fps(), 2)), 8, black)
window.blit(text, (545, 5))
# update display
pygame.display.update()
And also a pastebin here if it's easier to look at/copy.
I appreciate any help with this, I've been able to work out any other problem on my own, but I can't tell what I'm missing here.
I hope the below code helps. Although my program was a bit different because every time the ball hit the paddle we had to generate a new ball.
import random
from livewires import games, color
games.init(screen_width = 640, screen_height = 480, fps = 50)
class Ball(games.Sprite):
quit_label = games.Text(value = "Press Q to Quit", size = 25, color = color.white, top = 5, right = 130,
is_collideable = False)
games.screen.add(quit_label)
def update(self):
if self.right > games.screen.width:
self.dx = -self.dx
if self.left < 0:
self.game_over()
if self.bottom > games.screen.height or self.top < 0:
self.dy = -self.dy
#pressing 'q' quits the game
if games.keyboard.is_pressed(games.K_q):
self.game_over()
def bounce(self):
self.dx = -self.dx
def game_over(self):
""" End the game. """
end_message = games.Message(value = "Game Over",
size = 90,
color = color.red,
x = games.screen.width/2,
y = games.screen.height/2,
lifetime = 3 * games.screen.fps,
after_death = games.screen.quit,
is_collideable = False)
games.screen.add(end_message)
self.destroy()
class Paddle(games.Sprite):
image = games.load_image("paddle.bmp")
score = games.Text(value = 0, size = 25, color = color.white, top = 15,
right = games.screen.width - 10, is_collideable = False)
games.screen.add(score)
def __init__(self):
super(Paddle, self).__init__(image = Paddle.image, x = games.mouse.x, bottom = games.screen.height)
def update(self):
""" Move to mouse y position. """
self.y = games.mouse.y
if self.left > 0:
self.left = 10
if self.right > games.screen.height:
self.right = games.screen.height
self.check_catch()
def check_catch(self):
for ball in self.overlapping_sprites:
Paddle.score.value += 1
ball_image2 = games.load_image("ball.bmp")
ball2 = Ball(image = ball_image2,
x = games.screen.width/2,
y = games.screen.height/2,
dx = 1,
dy = 1)
games.screen.add(ball2)
ball.bounce()
def main():
wall_image = games.load_image("background.bmp", transparent = False)
games.screen.background = wall_image
ball_image = games.load_image("ball.bmp")
the_ball = Ball(image = ball_image,
x = games.screen.width/2,
y = games.screen.height/2,
dx = 1,
dy = 1)
games.screen.add(the_ball)
the_paddle = Paddle()
games.screen.add(the_paddle)
games.mouse.is_visible = False
games.screen.mainloop()
# kick it off!
main()
Well In a game I am working on I have recently allowed mouse click to shoot wherever the mouse is. But the bullets will only shoot at either a 0 degree angle or 45 degree angle. I am wanting to try and make this to be 360 degrees. Here is the code for my main game file:
import pygame, sys
import random
import pygame.mixer
import Funk, math
from time import sleep
from player import *
from zombie import *
from level import *
from bullet import *
from constants import *
from Drops import *
from menus import *
from meteors import *
import menu as dm
class Game():
def __init__(self):
pygame.init()
pygame.mixer.init()
pygame.mixer.music.load('data/sounds/menugame.ogg')
pygame.mixer.music.set_volume(0.5)
pygame.mixer.music.play(-1)
# A few variables
self.gravity = .50
self.red = (255, 0, 0)
self.darkred = (200, 0, 0)
self.darkblue = (0, 0, 200)
self.darkgreen = (0, 200, 0)
self.gameover = pygame.image.load('data/images/gameover.png')
self.victory = pygame.image.load('data/images/victory.png')
# Bullets and Drops
self.bullets = []
self.gameDrops = []
# Screen
icon = pygame.image.load('data/icons/moonsurvival.bmp')
size = SCREEN_WIDTH, SCREEN_HEIGHT
self.screen = pygame.display.set_mode(size)
pygame.display.set_caption('Moon Survival!')
pygame.display.set_icon(icon)
self.screen_rect = self.screen.get_rect()
# Moon / Background
self.moon = Background()
self.text1 = pygame.image.load('data/images/TextSlides/Text1.jpg')
self.text2 = pygame.image.load('data/images/TextSlides/Text2.jpg')
# Zombies and boss
self.zombies = []
self.bosses = []
#for i in range(15):
# self.zombies.append( Zombie(random.randint(0,1280), random.randint(0,0)) )
self.zombieskilled = 0
# Spawn time
self.last_spawn_time = 0
# Meteors
self.meteors = []
# Menus
self.menuStartGame = MenuStartGame(self.screen, self)
self.menuAbout = MenuAbout(self.screen, self)
#self.menuSettings = MenuSettings(self.screen, self)
self.menuScene = MenuScene(self.screen, self)
self.menuGameOver = MenuGameOver(self.screen, self)
#self.menuGameFinish = MenuGameFinish(self.screen, self)
# Player
self.player = Player(25, 320, self.gravity)
# Font for text
self.font = pygame.font.SysFont(None, 72)
self.point = self.player.rect.x, self.player.rect.y
self.max_radius = math.hypot(self.screen_rect.w, self.screen_rect.h)
self.mouse_angle = (0, 0)
# game over
self.gameover_text = self.font.render("The Aliens Are Too Good", -1, (255, 0, 0))
self.gameover_rect = self.gameover_text.get_rect(center=self.screen.get_rect().center)
# game state
self.game_state = STATE_MENU
def run(self):
clock = pygame.time.Clock()
# "state machine"
RUNNING = True
PAUSED = False
GAME_OVER = False
# Game loop
while RUNNING:
# (all) Events
if self.game_state == STATE_INGAME:
print(self.mouse_angle)
for event in pygame.event.get():
if event.type == pygame.QUIT:
RUNNING = False
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_s:
if self.player.power == POWER_TRIBULLETS:
self.bullets.append(Bullet(self.player.rect.x + 35, self.player.rect.y + 35, self.mouse_angle))
self.bullets.append(Bullet(self.player.rect.x + 30, self.player.rect.y + 30, self.mouse_angle))
self.bullets.append(Bullet(self.player.rect.x + 35, self.player.rect.y + 25, self.mouse_angle))
else:
self.bullets.append(Bullet(self.player.rect.x + 30, self.player.rect.y + 30, self.mouse_angle))
if event.key == pygame.K_ESCAPE:
RUNNING = False
elif event.key == pygame.K_p:
# set state to paused
self.game_state = STATE_PAUSED
elif event.type == pygame.MOUSEBUTTONDOWN:
if event.button == 1:
if self.player.power == POWER_TRIBULLETS:
self.bullets.append(Bullet(self.player.rect.x + 35, self.player.rect.y + 35, self.mouse_angle))
self.bullets.append(Bullet(self.player.rect.x + 30, self.player.rect.y + 30, self.mouse_angle))
self.bullets.append(Bullet(self.player.rect.x + 35, self.player.rect.y + 25, self.mouse_angle))
else:
self.bullets.append(Bullet(self.player.rect.x + 30, self.player.rect.y + 30, self.mouse_angle))
# Player/Zombies events
self.player.handle_events(event)
# (all) Movements / Updates
self.player_move()
self.player.update()
for z in self.zombies:
self.zombie_move(z)
z.update(self.screen.get_rect())
for boss in self.bosses:
self.boss_move(boss)
boss.update(self.screen.get_rect())
for b in self.bullets:
b.update()
for tile in self.moon.get_surrounding_blocks(b):
if tile is not None:
if pygame.sprite.collide_rect(b, tile):
# Destroy block
x = tile.rect.x / tile.rect.width
y = tile.rect.y / tile.rect.height
self.moon.levelStructure[x][y] = None
try:
self.bullets.remove(b)
except:
continue
for m in self.meteors:
m.update()
for tile in self.moon.get_surrounding_blocks(m):
if tile is not None:
if pygame.sprite.collide_rect(m, tile):
# Destroy block
x = tile.rect.x / tile.rect.width
y = tile.rect.y / tile.rect.height
self.moon.levelStructure[x][y] = None
self.moon.levelStructure[x + 1][y + 1] = None
self.moon.levelStructure[x - 1][y - 1] = None
self.moon.levelStructure[x + 2][y + 2] = None
self.moon.levelStructure[x - 2][y - 2] = None
try:
self.meteors.remove(m)
except:
continue
self.check_game_state()
# (all) Display updating
self.moon.render(self.screen)
for z in self.zombies:
z.render(self.screen)
for boss in self.bosses:
boss.render(self.screen)
for b in self.bullets:
b.render(self.screen)
for m in self.meteors:
m.render(self.screen)
for drop in self.gameDrops:
drop.render(self.screen)
self.player.render(self.screen)
self.updateMousePosition(self.screen, pygame.mouse.get_pos())
Funk.text_to_screen(self.screen, 'Level 1', 5, 675)
Funk.text_to_screen(self.screen, 'Health: {0}'.format(self.player.health), 5, 0)
Funk.text_to_screen(self.screen, 'Score: {0}'.format(self.player.score), 400, 0)
Funk.text_to_screen(self.screen, 'Time: {0}'.format(self.player.alivetime), 750, 0)
Funk.text_to_screen(self.screen, 'Kills: {0}'.format(self.zombieskilled), 5, 50)
Funk.text_to_screen(self.screen, 'Lives: {0}'.format(self.player.lives), 300, 50)
elif self.game_state == STATE_GAMEOVER:
self.menuGameOver.draw()
self.menuGameOver.update()
elif self.game_state == STATE_SETTINGS:
self.menuSettings.draw()
self.menuSettings.update()
elif self.game_state == STATE_ABOUT:
self.menuAbout.draw()
self.menuAbout.update()
elif self.game_state == STATE_SCENE:
self.menuScene.draw()
self.menuScene.update()
elif self.game_state == STATE_MENU:
self.menuStartGame.draw()
self.menuStartGame.update()
elif self.game_state == STATE_PAUSED:
# (all) Display updating
if self.game_state == STATE_INGAME:
if event.type == pygame.QUIT:
RUNNING = False
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
RUNNING = False
choose = dm.dumbmenu(self.screen, [
'Resume Game',
'Menu',
'Quit Game'], 200, 200,'orecrusherexpanded',100,0.75,self.darkred,self.red)
if choose == 0:
print "You choose 'Start Game'."
# set state to ingame
self.game_state = STATE_INGAME
elif choose == 1:
print "You choose 'Controls'."
if choose == 2:
print "You choose 'Quit Game'."
pygame.quit()
sys.exit()
#for event in pygame.event.get():
self.moon.render(self.screen)
for z in self.zombies:
z.render(self.screen)
for boss in self.bosses:
boss.render(self.screen)
for b in self.bullets:
b.render(self.screen)
for m in self.meteors:
m.render(self.screen)
self.player.render(self.screen)
pygame.display.update()
# FTP
clock.tick(100)
# --- the end ---
pygame.quit()
def updateMousePosition(self, surface, mouse):
x_comp, y_comp = mouse[0] - self.point[0], mouse[1] - self.point[1]
self.mouse_angle = math.atan2(y_comp, x_comp)
x = self.max_radius * math.cos(self.mouse_angle) + self.point[0]
y = self.max_radius * math.sin(self.mouse_angle) + self.point[1]
pygame.draw.line(surface, pygame.Color("white"), self.point, (x, y))
def check_game_state(self):
elapsed_time = pygame.time.get_ticks()
if elapsed_time > self.last_spawn_time + 10:
# Spawn aliens
if len(self.zombies) <= 10:
self.zombies.append(Zombie(random.randint(0,1280), random.randint(0,0)))
# Spawned! Change last spawn time!
self.last_spawn_time = elapsed_time
meteor_time = pygame.time.get_ticks()
if meteor_time > self.last_spawn_time + random.randint(1000, 3000):
# Spawn meteors
if len(self.meteors) <= 1:
self.meteors.append(Meteor(random.randint(0,1280), random.randint(-100,0)))
# Spawned! Change last spawn time!
self.last_spawn_time = meteor_time
def player_move(self):
# Line start
self.point = self.player.rect.x + 30, self.player.rect.y + 30
# add gravity
self.player.do_jump()
# simulate gravity
self.player.on_ground = False
if not self.player.on_ground and not self.player.jumping:
self.player.velY = 4
# Drops
for drop in self.gameDrops:
if pygame.sprite.collide_rect(self.player, drop):
if type(drop) == HealthDrop:
self.player.health += 50
self.gameDrops.remove(drop)
elif type(drop) == SuperHealthDrop:
self.player.health += 1000
self.gameDrops.remove(drop)
elif type(drop) == TriBullets:
self.player.power = POWER_TRIBULLETS
self.gameDrops.remove(drop)
elif type(drop) == ShieldDrop:
self.player.power = POWER_SHIELD
self.gameDrops.remove(drop)
# Health
for zombie in self.zombies:
if pygame.sprite.collide_rect(self.player, zombie):
if self.player.power == POWER_SHIELD:
self.player.health -= 1
else:
self.player.health -= 5
# check if we die
if self.player.health <= 0:
self.player.power = POWER_NONE
self.player.lives -= 1
self.player.rect.x = 320
self.player.rect.y = 320
self.player.health += 200
if self.player.lives <= 0:
self.game_state = STATE_GAMEOVER
# move player and check for collision at the same time
self.player.rect.x += self.player.velX
self.check_collision(self.player, self.player.velX, 0)
self.player.rect.y += self.player.velY
self.check_collision(self.player, 0, self.player.velY)
def zombie_move(self, zombie_sprite):
# add gravity
zombie_sprite.do_jump()
percentage = random.randint(0, 100)
# simualte gravity
zombie_sprite.on_ground = False
if not zombie_sprite.on_ground and not zombie_sprite.jumping:
zombie_sprite.velY = 4
# Zombie damage
for zombie in self.zombies:
for b in self.bullets:
if pygame.sprite.collide_rect(b, zombie):
#The same bullet cannot be used to kill
#multiple zombies and as the bullet was
#no longer in Bullet.List error was raised
zombie.health -= 10
self.bullets.remove(b)
if zombie.health <= 0:
if (percentage >= 0) and (percentage < 40):
self.gameDrops.append(HealthDrop(zombie.rect.x + 10, zombie.rect.y + 30))
elif (percentage >= 0) and (percentage < 1):
self.gameDrops.append(SuperHealthDrop(zombie.rect.x + 20, zombie.rect.y + 30))
elif (percentage >= 1) and (percentage < 20):
self.gameDrops.append(TriBullets(zombie.rect.x + 30, zombie.rect.y + 30, self.player.direction))
elif (percentage >= 1) and (percentage < 50):
self.gameDrops.append(ShieldDrop(zombie.rect.x + 40, zombie.rect.y + 30))
self.zombieskilled += 1
self.player.score += 20
self.zombies.remove(zombie)
break
# move zombie and check for collision
zombie_sprite.rect.x += zombie_sprite.velX
self.check_collision(zombie_sprite, zombie_sprite.velX, 0)
zombie_sprite.rect.y += zombie_sprite.velY
self.check_collision(zombie_sprite, 0, zombie_sprite.velY)
def check_collision(self, sprite, x_vel, y_vel):
# for every tile in Background.levelStructure, check for collision
for block in self.moon.get_surrounding_blocks(sprite):
if block is not None:
if pygame.sprite.collide_rect(sprite, block):
# we've collided! now we must move the collided sprite a step back
if x_vel < 0:
sprite.rect.x = block.rect.x + block.rect.w
if type(sprite) is Zombie:
# the sprite is a zombie, let's make it jump
if not sprite.jumping:
sprite.jumping = True
sprite.on_ground = False
if x_vel > 0:
sprite.rect.x = block.rect.x - sprite.rect.w
if type(sprite) is Zombie:
# the sprite is a zombie, let's make it jump
if not sprite.jumping:
sprite.jumping = True
sprite.on_ground = False
if y_vel < 0:
sprite.rect.y = block.rect.y + block.rect.h
if y_vel > 0 and not sprite.on_ground:
sprite.on_ground = True
sprite.rect.y = block.rect.y - sprite.rect.h
#---------------------------------------------------------------------
Game().run()
Here is the code for the bullets:
import pygame, math
class Bullet(pygame.sprite.Sprite):
def __init__(self, x, y, angle):
self.image = pygame.image.load('data/images/Sprites/laser.png')
self.rect = self.image.get_rect()
self.rect.x = x
self.rect.y = y
self.velX = math.cos(angle * math.pi / 180) * 8
self.velY = math.sin(angle * math.pi / 180) * 8
# self.velX = 8
# self.velX = -8
# Bullet updates
def update(self):
# Velocity
self.rect.x += self.velX
self.rect.y += self.velY
def render(self, surface):
surface.blit(self.image, self.rect)
self.mouse_angle is already in radians. If you multiply it again by math.pi / 180, as you do in Bullet.__init__(), it will always give a value very close to zero.