I'm writing a basic Snake game in Pygame, but the body of the snake is not extending after its eaten 4 pieces of food, nor does it extend after the first bite. I'm creating a new body object after each bite, and storing it in a list. x and y variables are used to store the position of the head prior to its movement, which in turn I use as the coordinates for the first segment of the snake's body. I'm then trying to iterate over this list, creating new objects with the x and y coordinates of the previous body segment to create the tail effect. Why is it stopping short?
import pygame
from pygame.locals import *
import random
import sys
pygame.init()
FPS = 30
fpsClock = pygame.time.Clock()
WIN_WIDTH = 680 #width of window
WIN_HEIGHT = 500 #height of window
DISPLAY = (WIN_WIDTH, WIN_HEIGHT) #variable for screen display
DEPTH = 32 #standard
FLAGS = 0 #standard
BLACK = (0, 0, 0) #black
RED = (255, 0, 0) #red
GOLD = (255, 215, 0)
IDK = (178, 154, 96)
screen = pygame.display.set_mode(DISPLAY, FLAGS, DEPTH)
pygame.display.set_caption('Snake')
snake_parts = [1]
Score = 0
speed = 10
snakex = 15
snakey = 70
size = 20
Snakes = 1
# --- classes ---
class Snake(pygame.Rect):
def __init__(self, x, y, screen, size, colour):
pygame.Rect.__init__(self, x, y, size, 20)
self.screen = screen
self.colour = colour
self.x = x
self.y = y
def draw(self, screen):
pygame.draw.rect(self.screen, self.colour, self)
def coordinates(self):
return self.x, self.y
class Food(pygame.Rect):
def __init__(self, x, y, screen):
pygame.Rect.__init__(self, x, y, 20, 20)
self.screen = screen
def draw(self, screen):
pygame.draw.rect(self.screen, GOLD, self)
# --- functions ---
def get_food_pos(WIN_WIDTH, WIN_HEIGHT):
WIN_WIDTH = random.randint(1, WIN_WIDTH)
WIN_HEIGHT = random.randint(1, WIN_HEIGHT)
return WIN_WIDTH, WIN_HEIGHT
eaten = True
pressed_right = True
pressed_left = False
pressed_up = False
pressed_down = False
pygame.key.set_repeat(10,10)
while True:
screen.fill(BLACK)
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
elif event.type == pygame.KEYDOWN: # check for key presses
if event.key == pygame.K_LEFT: # left arrow turns left
pressed_left = True
pressed_right = False
pressed_up = False
pressed_down = False
elif event.key == pygame.K_RIGHT: # right arrow turns right
pressed_right = True
pressed_left = False
pressed_up = False
pressed_down = False
elif event.key == pygame.K_UP: # up arrow goes up
pressed_up = True
pressed_right = False
pressed_left = False
pressed_down = False
elif event.key == pygame.K_DOWN: # down arrow goes down
pressed_down = True
pressed_right = False
pressed_up = False
pressed_left = False
x = snakex
y = snakey
if pressed_left:
snakex -= speed
elif pressed_right:
snakex += speed
elif pressed_up:
snakey -= speed
elif pressed_down:
snakey += speed
snake_parts[0] = Snake(snakex, snakey, screen, int(size), IDK)
snake_parts[0].draw(screen)
if eaten:
foodx, foody = get_food_pos(WIN_WIDTH, WIN_HEIGHT)
eaten = False
my_food = Food(foodx, foody, screen)
my_food.draw(screen)
if snake_parts[0].colliderect(my_food):
eaten = True
screen.fill(BLACK)
a_snake = Snake(snakex, snakey, screen, int(size), RED)
snake_parts.append(a_snake)
if len(snake_parts) >= 1:
for i in range(1, len(snake_parts)-1):
tempx, tempy = snake_parts[i].coordinates()
snake_parts[i] = Snake(x, y, screen, int(size), RED)
snake_parts[i].draw(screen)
snake_parts[i+1] = Snake(tempx, tempy, screen, int(size), RED)
x, y = tempx, tempy
Figured it out, the issue was this line:
snake_parts[i+1] = Snake(tempx, tempy, screen, int(size), RED)
removed it and it's working fine.
Related
This question already has an answer here:
Replace a rectangle with an Image in Pygame
(1 answer)
Closed last year.
So I don't know how to turn the rectangle representing the player into an image (spaceship). I know it must be simple, but after a few hours with this I'm a little frustrated, so I'm looking for help :(
bg_color = pygame.Color('black')
text_color = pygame.Color('darkgrey')
obstacles_color = pygame.Color('darkred')
player_color = pygame.Color('yellow')
fps = 60
window_height = 1200
window_width = 1200
player_speed = 4
player_size = 8
player_max_up = 125
obstacle_spawn_rate = 1
obstacle_min_size = 3
obstacle_max_size = 6
obstacle_min_speed = 2
obstacle_max_speed = 2
class Player:
def __init__(self):
self.size = player_size
self.speed = player_speed
self.color = player_color
self.position = (window_width / 2, (window_height - (window_height / 10)))
def draw(self, surface):
r = self.get_rect()
pygame.draw.rect(surface, self.color, r)
def move(self, x, y):
newX = self.position[0] + x
newY = self.position[1] + y
if newX < 0 or newX > window_width - player_size:
newX = self.position[0]
if newY < window_height - player_max_up or newY > window_height - player_size:
newY = self.position[0]
self.position = (newX, newY)
def collision_detection(self, rect):
r = self.get_rect()
return r.colliderect(rect)
def get_rect(self):
return pygame.Rect(self.position, (self.size, self.size))
class Obstacles:
def __init__(self):
self.size = random.randint(obstacle_min_size, obstacle_max_size)
self.speed = random.randint(obstacle_min_speed, obstacle_max_speed)
self.color = obstacles_color
self.position = (random.randint(0, window_width - self.size), 0 - self.size)
def draw(self, surface):
r = self.get_rect()
pygame.draw.rect(surface, self.color, r)
def move(self):
self.position = (self.position[0], self.position[1] + self.speed)
def is_off_window(self):
return self.position[1] > window_height
def get_rect(self):
return pygame.Rect(self.position, (self.size, self.size))
class World:
def __init__(self):
self.reset()
def reset(self):
self.player = Player()
self.obstacles = []
self.gameOver = False
self.score = 0
self.obstacles_counter = 0
self.moveUp = False
self.moveDown = False
self.moveLeft = False
self.moveRight = False
def is_game_over(self):
return self.gameOver
def update(self):
self.score += 1
if self.moveUp:
self.player.move(0, - player_speed)
if self.moveUp:
self.player.move(0, player_speed)
if self.moveLeft:
self.player.move(-player_speed, 0)
if self.moveRight:
self.player.move(player_speed, 0)
for each in self.obstacles:
each.move()
if self.player.collision_detection(each.get_rect()):
self.gameOver = True
if each.is_off_window():
self.obstacles.remove(each)
self.obstacles_counter += 1
if self.obstacles_counter > obstacle_spawn_rate:
self.obstacles_counter = 0
self.obstacles.append(Obstacles())
def draw(self, surface):
self.player.draw(surface)
for each in self.obstacles:
each.draw(surface)
def movement_keys(self, event):
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_UP:
self.moveUp = True
if event.key == pygame.K_DOWN:
self.moveDown = True
if event.key == pygame.K_LEFT:
self.moveLeft = True
if event.key == pygame.K_RIGHT:
self.moveRight = True
if event.type == pygame.KEYUP:
if event.key == pygame.K_UP:
self.moveUp = False
if event.key == pygame.K_DOWN:
self.moveDown = False
if event.key == pygame.K_LEFT:
self.moveLeft = False
if event.key == pygame.K_RIGHT:
self.moveRight = False
def run():
pygame.init()
clock = pygame.time.Clock()
window = pygame.display.set_mode((window_height, window_width))
pygame.display.set_caption("Avoid Obstacles")
surface = pygame.Surface(window.get_size())
surface = surface.convert()
world = World()
font = pygame.font.SysFont("Times", 35, "bold")
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.KEYDOWN and event.key == ord("r"):
world.reset()
else:
world.movement_keys(event)
if not world.is_game_over():
world.update()
window.fill(bg_color)
clock.tick(fps)
world.draw(window)
surface.blit(surface, (0, 0))
text = font.render("Score {0}".format(world.score), 1, text_color)
window.blit(text, (1, 1))
if world.is_game_over():
end = font.render("The end of your journey", 1, text_color)
window.blit(end, (window_width / 2 - 220, window_height / 2))
restart = font.render("Hit R to reset", 1, text_color)
window.blit(restart, (window_width / 2 - 120, window_height / 2 + 45))
pygame.display.update()
if __name__ == '__main__':
run()
pygame.quit()
I tried changing the draw function in the Player class, but still couldn't figure out how to do it correctly. I'm drawing an image of the spaceship on the screen/window, but I can't get it to move to the player rectangle.
I don't know what you've tried, but here's how to do this with a call to blit:
myimage = pygame.image.load("bar.png")
...
def draw(self, surface):
r = self.get_rect()
surface.blit(myimage, r)
The key point here is that you're giving blit the same coordinates that you were using to draw the rectangle. When I tried this, I got the correct/natural size of the image even though the r rectangle is of different dimensions. If that turns out to cause a problem, you could adjust the dimensions of the rectangle to be the same as the image. You also might want to adjust the coordinates of r such that the image is drawn centered on the location at which you wish to draw it.
The 'draw' family of functions are convenience functions that create Surface objects and then paint pixels on it that correspond to basic shapes (like circles, rectangles etc, filled or otherwise).
Instead, you need to create a Surface where the pixels have been initialised via an image. For this, you need the "image" family of functions (see https://www.pygame.org/docs/ref/image.html for image functions).
Other than that, everything in pygame is a surface, and you're manipulating and updating surfaces on the display, so your code should not change, whether your surfaces were initialised via 'draw' or 'image'.
My second game is a platformer. I drew all the spites, drew the background and the platform, but I cant move my character more than 45 pixels one way, even when it is supposed to move 5 pixels. I also copied some code from here and there, so I cant just search it up. This is very puzzling, please help.
Here is the code:
import sys
import pygame
screen = pygame.display.set_mode((1300, 700), pygame.RESIZABLE)
global bg
bg = pygame.image.load('Pictures/badground.png')
w = (0, 0, 0)
screen.fill(w)
screen.blit(bg, (0, 0))
level = 0
walking_l = (pygame.image.load('Pictures/walk_l.png'))
walking_r = (pygame.image.load('Pictures/walk_r.png'))
walking_l_2 = (pygame.image.load('Pictures/_stand.png'))
walking_r_2 = (pygame.image.load('Pictures/stand.png'))
stand = (pygame.image.load('Pictures/rstand.png'))
pf = (pygame.image.load('Pictures/platform.png'))
pygame.display.set_caption('Platformed')
class player(object):
def __init__(self, speed, width, height):
self.speed = speed
self.x = 650
self.y = 350
self.width = width
self.height = height
self.walk_l = False
self.walk_r = False
self.stand = True
self.jump = False
self.walk_count = 0
def reprint_win(self):
screen.fill(w)
screen.blit(bg, (0, 0))
def walk(self):
k = pygame.key.get_pressed()
if k[pygame.K_a]:
self.x -= self.speed
self.stand = False
self.walk_l = True
self.walk_r = False
self.jump = False
print(self.x)
screen.fill(w)
screen.blit(bg, (0, 0))
elif k[pygame.K_d]:
self.x += self.speed
self.stand = False
self.walk_r = True
self.walk_l = False
self.jump = False
print(self.y)
screen.fill(w)
screen.blit(bg, (0, 0))
elif k[pygame.K_w] and self.walk_r and not self.jump:
self.stand = False
self.walk_r = True
self.walk_l = False
self.jump = True
screen.fill(w)
screen.blit(bg, (0, 0))
else:
self.stand = True
self.walk_r = False
self.walk_l = False
self.jump = False
screen.fill(w)
screen.blit(bg, (0, 0))
while True:
for e in pygame.event.get():
man = player(5, 64, 64)
if e.type == pygame.QUIT:
sys.exit()
if e.type == pygame.KEYDOWN:
man.walk()
screen.blit(stand, (man.x, man.y))
pygame.display.update()
elif e.type == pygame.KEYDOWN:
man.walk()
screen.blit(stand, (man.x, man.y))
pygame.display.update()
The method walk() of the class player changes the instance attribute, but id doesn't draw anything.
Add a method draw, which draw the player dependent on the instance attributes:
class player(object):
# [...]
def walk(self):
self.stand, self.walk_l, self.walk_r, self.jump = False, False, False, False
k = pygame.key.get_pressed()
if k[pygame.K_a]:
self.x -= self.speed
self.walk_l = True
elif k[pygame.K_d]:
self.x += self.speed
self.walk_r = True
elif k[pygame.K_w] and self.walk_r and not self.jump:
self.jump = True
else:
self.stand = True
def draw(self, surf):
if self.walk_l:
surf.blit(walking_l, (self.x, self.y))
elif self.walk_r:
surf.blit(walking_r, (self.x, self.y))
else:
surf.blit(stand, (self.x, self.y))
You have to draw the entire scene in every frame. Do the drawing to the application loop rather then the event loop.
Furthermore the instance of palyer has to be created before the application loop and invoke man.mvoe() in every frame.
Use pygame.time.Clock() .tick() to control the frames per second:
man = player(5, 64, 64)
clock = pygame.time.Clock()
FPS = 60
while True:
clock.tick(FPS)
for e in pygame.event.get():
if e.type == pygame.QUIT:
sys.exit()
man.walk()
screen.blit(bg, (0, 0))
man.draw(screen)
pygame.display.update()
I have made a python game, and when you press space it shoots a bullet (a line). It is only able to shoot once though. I was wondering how I could make it shoot multiple times?
shotStartX = x + 30
shotStartY = y + 20
shotEndX = x + 30
shotEndY = y
shoot = False
while True:
if event.type == pygame.KEYDOWN:
elif event.key == pygame.K_SPACE:
shoot = True
gameDisplay.fill(blue)
if shoot:
pygame.draw.line(gameDisplay,red,(shotStartX,shotStartY),(shotEndX,shotEndY),5)
shotStartY -= 10
shotEndY -= 10
gameDisplay.blit(rocketImg,(x,y))
pygame.display.update()
clock.tick(30)
I would create two classes, bullet and bullets and limit the firing rate to a certain time. Try this:
import pygame
import time
# define some colors
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
W = 480
H = 720
FPS = 60
BULLET_SPEED = 5
BULLET_FIRING_RATE = 0.5 # seconds
class bullet:
def __init__(s, x, y): # x, y = starting point
s.x = x
s.y = y
s.dead = False
def draw(s):
global DS
global WHITE
pygame.draw.circle(DS, WHITE, (s.x, s.y), 10)
def move(s):
global BULLET_SPEED
s.y -= BULLET_SPEED
if s.y <= 0:
s.dead = True
class bullets:
def __init__(s):
s.container = []
s.lastBulletTime = time.time() -BULLET_FIRING_RATE
def add(s, x, y):
global BULLET_FIRING_RATE
now = time.time()
if now - s.lastBulletTime >= BULLET_FIRING_RATE:
s.container.append(bullet(x, y))
s.lastBulletTime = now
def do(s):
deadBullets = []
for b in s.container:
b.draw()
b.move()
if b.dead: deadBullets.append(b)
for db in deadBullets:
s.container.remove(db)
pygame.init()
DS = pygame.display.set_mode((W, H))
CLOCK = pygame.time.Clock()
BULLETS = bullets()
# press escape to exit
while True:
e = pygame.event.get()
if pygame.key.get_pressed()[pygame.K_ESCAPE]: break
mx, my = pygame.mouse.get_pos()
mb = pygame.mouse.get_pressed()
if mb[0]:
BULLETS.add(mx, my)
DS.fill(BLACK)
BULLETS.do()
pygame.draw.circle(DS, WHITE, (mx, my), 40)
pygame.display.update()
CLOCK.tick(FPS)
pygame.quit()
I've written a game where the main character can shoot daggers on mouseclick, and move around with the up, down, left, and right keys. THe character also follows the mouse around. I have added the villains into the screen, however I am unsure of how to make a rect for my daggers. My intention is to use colliderect when the dagger and the villain collide; and recode the villain to disappear, and code it off of the screen and have him reappear. However; before I can do this I need to make a rect for my daggers; which I, for whatever reason cannot find out.
This is the portion of the code in which I define my rects variables and rect:
xPlayer = 200
yPlayer = 275
dxPlayer = 0
dyPlayer = 0
playerPosition = (200,275)
daggers = []
angle = 0
villainStartx = 800
villainStarty = random.randrange(0, 550)
villainSpeed = -10
villainWidth = 100
villainHeight = 100
villainTWOStartx = 800
villainTWOStarty = random.randrange(0, 550)
villainTWOSpeed = -20
villainTWOWidth = 100
villainTWOHeight = 100
villainRect = pygame.Rect(villainStartx, villainStarty, villainWidth, villainHeight)
villainTWORect = pygame.Rect(villainTWOStartx, villainTWOStarty, villainTWOWidth, villainTWOHeight)
player = pygame.Rect(xPlayer, yPlayer, 160, 146)
This is the portion of my code where I draw the daggers to the screen on mouseclick:
filtered_daggers = []
for shot in daggers:
if not outOfBounds(shot[0]):
filtered_daggers.append(shot)
daggers = filtered_daggers
for shot in daggers:
shot[0][0] += shot[1][0]
shot[0][1] += shot[1][1]
screen.blit(cloudSky, (0,0))
screen.blit(playerRotate, playerPositionNew)
for shot in daggers:
x, y = shot[0]
screen.blit(shot[2], shot[0])
And if necessary, below is my entire code:
#Import the necessary modules
import pygame
import sys
import os
import math
import random
#Initialize pygame
pygame.init()
# Set the size for the surface (screen)
screenSize = (900,600)
screen = pygame.display.set_mode((screenSize),0)
# Set the caption for the screen
pygame.display.set_caption("Neverland")
#Define Colours
WHITE = (255,255,255)
BLUE = (0,0,255)
BLACK = (0,0,0)
GRAY = (128, 128, 128)
MAROON = (128, 0, 0)
NAVYBLUE = (0, 0, 128)
OLIVE = (128, 128, 0)
PURPLE = (128, 0, 128)
TEAL = (0,128,128)
PINK = (226,132,164)
MUTEDBLUE = (155,182,203)
PLUM = (221,160,221)
#Clock Setup
clock = pygame.time.Clock()
#Load Images
peterPlayer = pygame.image.load('pixelPirateOne.png')
nightBackground = pygame.image.load ('skyTwo_1.png')
daggerPlayer = pygame.image.load('daggerPlayer.png')
captHook = pygame.image.load('/pixelCaptainHook.png')
cloudSky = pygame.image.load('cloudSky.png')
pirateTwo = pygame.image.load('pixelPirateTwo.png')
#Define All Variables
xPlayer = 200
yPlayer = 275
dxPlayer = 0
dyPlayer = 0
playerPosition = (200,275)
accuracyShot = [0,0]
daggers = []
angle = 0
healthValue=194
villainStartx = 800
villainStarty = random.randrange(0, 550)
villainSpeed = -10
villainWidth = 100
villainHeight = 100
villainTWOStartx = 800
villainTWOStarty = random.randrange(0, 550)
villainTWOSpeed = -20
villainTWOWidth = 100
villainTWOHeight = 100
villainRect = pygame.Rect(villainStartx, villainStarty, villainWidth, villainHeight)
villainTWORect = pygame.Rect(villainTWOStartx, villainTWOStarty, villainTWOWidth, villainTWOHeight)
player = pygame.Rect(xPlayer, yPlayer, 160, 146)
#dagger = pygame.Rect(
def quitGame():
pygame.quit()
sys.exit()
def outOfBounds(shot):
return shot[0] < -40 or shot[0] > 900 or shot[1] < -40 or shot[1] > 600
def villains(x,y):
screen.blit(captHook, (x,y))
def villainsTwo(x,y):
screen.blit(pirateTwo, (x,y))
go = True
while go:
#Quit Game
for event in pygame.event.get():
if event.type == pygame.QUIT:
quitGame()
#Move Player
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
dxPlayer -= 25
elif event.key == pygame.K_RIGHT:
dxPlayer += 25
elif event.key == pygame.K_UP:
dyPlayer -= 25
elif event.key == pygame.K_DOWN:
dyPlayer += 25
elif event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
dxPlayer = 0
elif event.key == pygame.K_UP or event.key == pygame.K_DOWN:
dyPlayer = 0
elif event.type == pygame.MOUSEBUTTONDOWN:
mousePosition = pygame.mouse.get_pos()
velx = math.cos(angle)*20
vely = math.sin(angle)*20
daggerImage = pygame.transform.rotate(daggerPlayer, -math.degrees(angle))
width, height = daggerImage.get_size()
daggers.append([[xPlayer,yPlayer],
[velx, vely], daggerImage])
#Update move player
xPlayer = xPlayer + dxPlayer
yPlayer = yPlayer + dyPlayer
pygame.display.update()
#Learned about atan2 from --> https://docs.python.org/2/library/math.html
#Allows To Rotate Player With Mouse
mousePosition = pygame.mouse.get_pos()
rise = mousePosition[1] - player.centery
run = mousePosition[0] - player.centerx
angle = math.atan2(rise, run)
playerRotate = pygame.transform.rotate(peterPlayer, -math.degrees(angle))
playerPositionNew = (xPlayer-playerRotate.get_rect().width/2, yPlayer-playerRotate.get_rect().height/2)
player = playerRotate.get_rect(center=player.center)
#Learned about cos and sin in python from --> https://docs.python.org/2/library/math.html
#Draw daggers to screen
filtered_daggers = []
for shot in daggers:
if not outOfBounds(shot[0]):
filtered_daggers.append(shot)
daggers = filtered_daggers
for shot in daggers:
shot[0][0] += shot[1][0]
shot[0][1] += shot[1][1]
screen.blit(cloudSky, (0,0))
screen.blit(playerRotate, playerPositionNew)
for shot in daggers:
x, y = shot[0]
screen.blit(shot[2], shot[0])
if villainRect.colliderect(dagger):
print(dagger)
pygame.display.update()
clock.tick(30)
#Drawing the villains at random
villains(villainStartx, villainStarty)
villainStartx +=villainSpeed
if villainStartx < -50:
villainStartx = random.randrange(800,900)
villainStarty = random.randrange(0,550)
villainsTwo(villainTWOStartx, villainTWOStarty)
villainTWOStartx +=villainTWOSpeed
if villainTWOStartx < -50:
villainTWOStartx = random.randrange(800,1000)
villainTWOStarty = random.randrange(0,550)
#Redrawing villain after collision- To be finished after defining dagger rect
pygame.display.update()
You can use an image for your dagger, and then get the rect properties from it:
dagger = pygame.image.load("dagger.png")
#you can then blit it on the screen:
screen.blit(dagger, (corrd1, corrd2))
dagger_rect = dagger.get_rect() #get the location of the dagger
if villianRect.colliderect(dagger_rect):
#do something
I want to know if my enemy is within 200 pixels of a defense tower so that I can start taking lives of the enemy. The enemy is moving and the defense is still FYI. if anyone can give me advice on how to do this that would be amazing. If I put my code up it will just confuse everyone because my code is very messy so just give me advice on how to do it thanks. Nick. I have added my code because I know I have done something wrong if anyone has the time to read through it and tell me what I am doing wrong which is probably everything that would be much appreciated.
import pygame
import math
from pygame.locals import *
def text():
font = pygame.font.SysFont("monospace", 14)
text = font.render("Start Round", True, black)
textpos = text.get_rect()
textpos.center = (790,675)
Background.blit(text, textpos)
def newRound():
pos = pygame.mouse.get_pos()
click = pygame.mouse.get_pressed()
if 730 < pos[0] < 850 and 650 < pos[1] < 800:
pygame.draw.rect(Background, (150,150,150), (730,650,120,50))
if click[0] == 1:
startGame()
else:
pygame.draw.rect(Background, (100,100,100), (730,650,120,50))
def startGame():
global startRound, endRound, intro
intro = 0
createRound()
intro = 1
startRound = True
endRound = False
def lifeText(lifes):
font = pygame.font.SysFont("monospace", 20)
text = font.render("Lives %s" % (lifes) , True, black)
textpos = text.get_rect()
textpos.center = (60,30)
Background.blit(text, textpos)
def life(self):
global hit, endRound, startRound, noEnemies, lifes
if noEnemies == 0 and lifes > 0:
startRound = False
endRound = True
if self.rect.x == 960:
hit = hit + 1
lifes = lifes - 1
if lifes == 0:
print("You have 0 lives Game Over")
pygame.quit()
if hit == 4:
startRound = False
endRound = True
hit = 0
noEnemies = noEnemies + 1
def createRound():
global enemies, noEnemies
enemies = []
x = -40
y = 210
for e in range(noEnemies):
x = x - 80
enemies.append(yellowEnemy(x, y, Background))
noEnemies = len(enemies)
def displayTower():
for tower in towers:
Background.blit(redtower, (tower))
class yellowEnemy(object):
image1 = pygame.image.load("enemySpriteFullHealth.jpg")
image2 = pygame.image.load("enemySpriteHalfHealth.jpg")
image3 = pygame.image.load("enemySpriteDead.jpg")
def __init__(self, x, y, Background):
self.Background = Background
self.Background_rect = Background.get_rect()
self.rect = self.image1.get_rect()
self.rect = self.image2.get_rect()
self.rect = self.image3.get_rect()
self.rect.x = x
self.rect.y = y
self.health = 20
self.dist_x = 2
self.dist_y = 0
def update(self):
self.rect.x += self.dist_x
self.rect.y += self.dist_y
def draw(self, Background):
timeDead = 0
if self.health > 9 and self.health < 21:
Background.blit(self.image1, self.rect)
elif self.health < 10 and self.health > 1:
Background.blit(self.image2, self.rect)
elif self.health < 1:
Background.blit(self.image3, self.rect)
self.dist_x = 0
life(self)
pygame.init()
width = 960
height = 720
black = (0,0,0)
lifes = 10
hit = 0
intro = 1
FPS = 200
noEnemies = 4
bx = 1000
by = 1000
towers = []
endRound = True
startRound = False
clicked = False
mx, my = pygame.mouse.get_pos()
clock = pygame.time.Clock()
test= False
mapImg = pygame.image.load("mapimage.jpg")
redtower = pygame.image.load("redTower.jpg")
Background = pygame.display.set_mode((width, height))
Background_rect = Background.get_rect()
while intro == 1:
mousePos = pygame.mouse.get_pos()
mousePressed = pygame.mouse.get_pressed()
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
if 530 < mousePos[0] < 590 and 650 < mousePos[1] < 710:
if mousePressed[0] == 1:
clicked = True
if clicked == True:
mx, my = pygame.mouse.get_pos()
pygame.display.update()
bx = 30
by = 30
if mousePressed[0] == 0:
clicked = False
tx = mx - bx
ty = my - by
towerCords = tx, ty
towers.append(towerCords)
if endRound == True:
Background.blit(mapImg, (0,0))
newRound()
text()
if startRound == True:
for enemy in enemies:
enemy.update()
Background.blit(mapImg, (0,0))
for enemy in enemies:
enemy.draw(Background)
Background.blit(redtower, (mx-bx, my-by))
if clicked == True:
pygame.draw.circle(Background, (220, 0, 0), (mx, my), 200, 4)
displayTower()
lifeText(lifes)
Background.blit(redtower, (530,650))
pygame.display.update()
clock.tick(FPS)
To find the distance between 2 points, you can use this code:
def get_dist(pos1, pos2):
return math.hypot(pos1[0] - pos2[0], pos1[1] - pos2[1])
This also requires you to import math at the beginning of your program.
If they are sprites, you can simply do:
import math
defense_rect = defense.get_rect()
if math.abs(enemy.rect.center - defense_rect.rect.center) <= 200:
# *do something*
The logic is to see if the enemy's center is 200 pixels from the defense's center from any position (hence the usage of math.abs() which is absolute value). When it is, you replace the comment with your code. Why does this work?
Check here.
Pygame has pygame.Rect() to keep object position and size.
Tower 200x200 with top left corner in point (0,0)
tower_rect = pygame.Rect(0,0, 300, 300)
or you can move it to have (0,0) in center
tower_rect = pygame.Rect(0,0, 300, 300)
tower_rect.center = (0, 0)
To check if other Rect() is fully inside tower
enemy_rect = pygame.Rect(10, 10, 50, 50)
if tower_rect.contains(enemy_rect):
or if it fully or only partially in tower (it coollides with tower)
if tower_rect.colliderect(enemy_rect):
You can event test with list of enemies
if tower_rect.collidelistall(list_of_enemies_rect):
or check one enemy with all towers
if enemy_rect.collidelistall(list_of_towers_rect):