I'm making a 2D game using pygame. I'm pretty new to python object oriented programming and don't quite understand classes and objects in full, so my coding approach might be a little weird. I have a player and entity class, and a key listener to change the player x and y (actually the background picture's x/y coords) relative to keys pressed. Currently, I have only one entity object named monster, because in order to properly move the player, I need to move every entity as well or else the entities will just move along with the player.
How do I reference every single entity I create simultaneously so I can change their x and y values, so I don't have to reference them one by one in the key listener functions?
Is there some entity.objects.all() sort of thing? Thank you if somebody can help, here's my code.
import os
import time
import threading
p.init()
c = p.time.Clock()
SCREEN_W = 800
SCREEN_H = 600
w = p.display.set_mode((SCREEN_W, SCREEN_H))
p.display.set_caption("Mason's Game")
walkRight = [p.image.load('game/r1.png'), p.image.load('game/r2.png'), p.image.load('game/r3.png'), p.image.load('game/r4.png'), p.image.load('game/r5.png'), p.image.load('game/r6.png'), p.image.load('game/r7.png'), p.image.load('game/r8.png'), p.image.load('game/r9.png')]
walkLeft = [p.image.load('game/l1.png'), p.image.load('game/l2.png'), p.image.load('game/l3.png'), p.image.load('game/l4.png'), p.image.load('game/l5.png'), p.image.load('game/l6.png'), p.image.load('game/l7.png'), p.image.load('game/l8.png'), p.image.load('game/l9.png')]
bg = p.image.load('game/bg.jpg')
char = p.image.load('game/standing.png')
mob = p.image.load('game/mob.png')
health = [p.image.load('game/h0.png'), p.image.load('game/h1.png'), p.image.load('game/h2.png'), p.image.load('game/h3.png'), p.image.load('game/h4.png'), p.image.load('game/h5.png'), p.image.load('game/h6.png'), p.image.load('game/h7.png'), p.image.load('game/h8.png'), p.image.load('game/h9.png'), p.image.load('game/h10.png'),]
def delay(x):
later = p.time.get_ticks() + x
if p.time.get_ticks() >= later:
pass
class entity(object):
def __init__(self, spawnx, spawny, x,y, level, health):
self.x=x
self.y=y
self.spawnx = spawnx
self.spawny= spawny
self.velocity=14
self.level = level
self.health = health
self.dead = False
def draw(self, w):
w.blit(mob, (self.x,self.y))
def printCoords(self):
print('x: ' , (-1*(m.x - monster.x) - 3600) - 300, " y: ", ((-1*(m.y - monster.y) - 3700) - 300)*-1)
def pace(self):
reachedRight = False
reachedLeft = False
if not reachedRight:
self.x += self.velocity/10
if self.x >= (self.spawnx + 100):
reachedRight = True
if reachedRight:
self.velocity *= -1
if self.x <= (self.spawnx - 100):
reachedLeft = True
if reachedLeft:
self.velocity*=-1
def stop(self):
self.velocity = 0
def followPlayer(self, player):
#if (abs(ogre.x - monster.x)) < 160 or (abs(ogre.y - monster.y)) < 160:
# monster.attackPlayer()
#if monster is left of player, close enough, but not too close
if self.x < player.x - 128 and self.x > player.x - 400:
self.velocity = 5
self.x += self.velocity
#if monster is right of player, close enough, but not too close
elif self.x > player.x + 128 and self.x < player.x + 400:
self.velocity = -5
self.x += self.velocity
#if monster is south of player, close enough, but not too close
if self.y < player.y - 128 and self.y > player.y - 400:
self.velocity = 5
self.y += self.velocity
#if monster is north of player, close enough, but not too close
elif self.y > player.y + 128 and self.y < player.y + 400:
self.velocity = -5
self.y += self.velocity
def attackPlayer(self, player):
def hitPlayer():
if player.health > 0:
player.sethealth(player.health - 1)
else:
player.death()
t=threading.Timer(5.0,hitPlayer)
t.start()
class mapp(object):
def __init__(self,x,y):
self.x= -3600
self.y= -3700
self.velocity = 14
self.left = False
self.right = False
self.standing = True
def draw(self, w):
w.blit(bg, (self.x,self.y))
class player(object):
def __init__(self, x, y, width, height):
self.x = x
self.y = y
self.width = width
self.height = height
self.vel = 14
self.j = False
self.jc = 10
self.right = False
self.left = False
self.walk = 0
self.standing = True
self.health = 10
self.travX = (-3600 - m.x)
self.travY = (-3700 - m.y)
def respawn(self):
time.sleep(0.4)
monster.x = (-1*(m.x - monster.x) - 3600)
monster.y = (-1*(m.y - monster.y) - 3700)
m.x += (-3600 - m.x)
m.y += (-3700 - m.y)
#monster.y += (-1*(m.y - monster.y) - 3700)
def death(self):
self.sethealth(10)
self.respawn()
def sethealth(self, x):
self.health = x
def draw(self,w):
w.blit(health[self.health], (730, 20))
if self.walk + 1 >= 27:
self.walk = 0
if not(self.standing):
if self.left:
w.blit(walkLeft[self.walk//3], (self.x,self.y))
self.walk += 1
elif self.right:
w.blit(walkRight[self.walk//3], (self.x,self.y))
self.walk += 1
else:
if self.left:
w.blit(walkLeft[0], (self.x,self.y))
else:
w.blit(walkRight[0], (self.x,self.y))
def drawGame():
m.draw(w)
ogre.draw(w)
monster.draw(w)
monster.followPlayer(ogre)
p.display.update()
####### main ############
m = mapp(-3600,-3700)
ogre = player(400, 300, 64, 64)
monster = entity(-200, 600, -200, 600, 5, 100)
monster2 = entity(-300, 630, -300, 630, 5, 100)
####### main ############
run = True
while run:
c.tick(27)
for event in p.event.get():
if event.type == p.QUIT:
run = False
k = p.key.get_pressed()
#monster.printCoords()
### left right up down player ####
if k[p.K_a]:
monster.x +=m.velocity
monster.spawnx+=m.velocity
m.x+=m.velocity
ogre.left = True
ogre.right = False
ogre.standing = False
elif k[p.K_d]:
monster.x -=m.velocity
monster.spawnx-=m.velocity
m.x-=m.velocity
ogre.right = True
ogre.left = False
ogre.standing = False
elif k[p.K_w]:
monster.y +=m.velocity
monster.spawny+=m.velocity
m.y+=m.velocity
ogre.right = False
ogre.left = False
ogre.standing = True
elif k[p.K_s]:
monster.y -=m.velocity
monster.spawny-=m.velocity
m.y-=m.velocity
ogre.right = False
ogre.left = False
ogre.standing = True
elif k[p.K_j]:
#monster.attackPlayer()
ogre.death()
else:
ogre.standing = True
ogre.walk = 0
drawGame()
p.quit()```
Set the variables move_x and move_y dependent on the pressed key:
move_x = 0
move_y = 0
if k[p.K_a]:
move_x = m.velocity
# [...]
elif k[p.K_d]:
move_x = -m.velocity
# [...]
elif k[p.K_w]:
move_y = m.velocity
# [...]
elif k[p.K_s]:
move_y = -m.velocity
# [...]
Create a list of monsters:
monsters = [
entity(-200, 600, -200, 600, 5, 100)
entity(-300, 630, -300, 630, 5, 100)
]
Move each individual monster in a for loop:
for monster in monsters:
monster.x += move_x
monster.y += move_y
monster.spawnx += move_x
monster.spawny += move_y
application loop:
m = mapp(-3600,-3700)
ogre = player(400, 300, 64, 64)
monsters = [
entity(-200, 600, -200, 600, 5, 100)
entity(-300, 630, -300, 630, 5, 100)
]
run = True
while run:
c.tick(27)
for event in p.event.get():
if event.type == p.QUIT:
run = False
k = p.key.get_pressed()
### left right up down player ####
move_x = 0
move_y = 0
if k[p.K_a]:
move_x = m.velocity
ogre.left = True
ogre.right = False
ogre.standing = False
elif k[p.K_d]:
move_x = -m.velocity
ogre.right = True
ogre.left = False
ogre.standing = False
elif k[p.K_w]:
move_y = m.velocity
ogre.right = False
ogre.left = False
ogre.standing = True
elif k[p.K_s]:
move_y = -m.velocity
ogre.right = False
ogre.left = False
ogre.standing = True
elif k[p.K_j]:
#monster.attackPlayer()
ogre.death()
else:
ogre.standing = True
ogre.walk = 0
for monster in monsters:
monster.x += move_x
monster.y += move_y
monster.spawnx += move_x
monster.spawny += move_y
m.x += move_x
m.y += move_y
drawGame()
Related
My code:
import pgzrun, pgzero, pygame, math, time, random, os
from pgzero.builtins import Actor, animate, keyboard
screen = pgzero.screen.Screen
# screen
WIDTH = 800
HEIGHT = 600
pygame.init()
pygame.mouse.set_visible(False)
os.chdir("c:/Users/carter.breshears/Documents/CSPVSC/Final/Images")
font = pygame.font.Font("Minecraft.ttf", 30)
# player images
playerIdle = pygame.image.load("playerIdle.png")
playerWalkImages = [pygame.image.load("playerRun1.png"), pygame.image.load("playerRun2.png"), pygame.image.load("playerRun3.png"), pygame.image.load("playerRun4.png")]
#variables
# gameloop
gameover = False
# classes
class Player:
def __init__(self, x, y):
self.x = x
self.y = y
self.animationCount = 0
self.movingRight = False
self.movingLeft = False
self.movingUp = False
self.movingDown = False
def main(self, screen):
if self.animationCount + 1 >= 24:
self.animationCount = 0
self.animationCount += 1
if self.movingRight or self.movingUp or self.movingDown:
screen.blit(pygame.transform.scale(playerWalkImages[self.animationCount//6], (40,74)), (self.x, self.y))
elif self.movingLeft:
screen.blit(pygame.transform.scale(pygame.transform.flip(playerWalkImages[self.animationCount//6], True, False), (40,74)), (self.x, self.y))
else:
screen.blit(pygame.transform.scale(playerIdle, (40,74)), (self.x, self.y)) ##### This line!
self.movingRight = False
self.movingLeft = False
self.movingUp = False
self.movingDown = False
class PlayerBullet:
def __init__(self, x, y, mouseX, mouseY):
self.x = x
self.y = y
self.mouseX = mouseX
self.mouseY = mouseY
speed = 6
self.angle = math.atan2(y - mouseY, x - mouseX)
self.x_vel = math.cos(self.angle) * speed
self.y_vel = math.sin(self.angle) * speed
def main(self, screen):
self.x -= int(self.x_vel)
self.y -= int(self.y_vel)
print("bang")
pygame.draw.circle(screen, "yellow", (self.x+16, self.y+16), 5)
class InvaderEnemy:
def __init__(self, x, y):
self.x = x
self.y = y
self.greenAnimationImages = [pygame.image.load("virus g.png"), pygame.image.load("virus g2.png")]
self.yellowAnimationImages = [pygame.image.load("virus y.png"), pygame.image.load("virus y2.png")]
self.blueAnimationImages = [pygame.image.load("virus b.png"), pygame.image.load("virus b2.png")]
self.redAnimationImages = [pygame.image.load("virus r.png"), pygame.image.load("virus r2.png")]
self.animationCount = 0
self.velocity = 1
self.lerpFactor = 0.05
def main(self, screen):
if self.animationCount + 1 == 8:
self.animationCount = 0
self.animationCount += 1
spawnPos = (random.randint(-1000, 1000), random.randint(-1000, 1000))
targetVector = pygame.math.Vector2(player.x, player.y)
enemyVector = pygame.math.Vector2(spawnPos.x, spawnPos.y)
newEnemyVector = pygame.math.Vector2(spawnPos.x, spawnPos.y)
distance = enemyVector.distance_to(targetVector)
minDistance = 25
maxDistance = 1000
if distance > minDistance:
directionVector = (targetVector - enemyVector)/2
self.minStep = max(0, distance - maxDistance)
self.maxStep = distance - minDistance
self.stepDistance = self.minStep + (self.maxStep - self.minStep) * self.lerpFactor
newEnemyVector = enemyVector + directionVector * self.stepDistance
return(newEnemyVector.x, newEnemyVector.y)
# player
player = Player(400,300)
displayScroll = [0,0]
# shooting
playerBullets = []
# invader
invaders = []
invaderEnemy = InvaderEnemy(100,100)
invaderSpawnRate = 1
# functions
def update():
# movement
keys = pygame.key.get_pressed()
if keys[pygame.K_a]:
displayScroll[0] -= 2
player.movingLeft = True
for bullet in playerBullets:
bullet.x += 2
if keys[pygame.K_d]:
displayScroll[0] += 2
player.movingRight = True
for bullet in playerBullets:
bullet.x -= 2
if keys[pygame.K_w]:
displayScroll[1] -= 2
player.movingUp = True
for bullet in playerBullets:
bullet.y += 2
if keys[pygame.K_s]:
displayScroll[1] += 2
player.movingDown = True
for bullet in playerBullets:
bullet.y -= 2
player.main(screen)
# shooting
mouseX, mouseY = pygame.mouse.get_pos()
for event in pygame.event.get():
if event.type == pygame.MOUSEBUTTONDOWN:
if event.button == 1:
playerBullets.append(PlayerBullet(player.x, player.y, mouseX, mouseY))
for bullet in playerBullets:
PlayerBullet.main(screen)
#enemies
global spawnPos
if time.perf_counter() - invaderSpawnRate > 1:
invaders.append(InvaderEnemy(spawnPos.x, spawnPos.y))
for invader in invaders:
InvaderEnemy.main(screen)
# run
pgzrun.go()
I've tried everything I know of, Im new to this. I know that it worked before because I tested this on my home computer but whenever I downloaded the file on my school computer it stopped working so something must have changed between python versions.
This question already has answers here:
Subsurface ValueError: 'subsurface rectangle outside surface area'
(1 answer)
Subsurface rect outside of surface area when using get_clip() in Pygame?
(1 answer)
How can I crop an image with Pygame?
(4 answers)
Closed 2 months ago.
I am currently working on a game on Pygame in Python. It is a player vs player battle game. When the program is run the value error subsurface rectangle outside surface area is shown. I searched about the error but could not understand about it as I am new to Pygame.
My program-
import pygame
from Players import Characters
pygame.init()
#Game window
swidth = 1000
sheight= 600
s=pygame.display.set_mode((swidth, sheight))
pygame.display.set_caption("Brawler")
#Framerate
clock = pygame.time.Clock()
FPS = 60
#Game variables
count=3
last_count_update=pygame.time.get_ticks()
score = [0, 0]#player scores. [P1, P2]
round_over = False
round_cooldown = 2000
#Player variables
Knight_size = 278
Knight_scale = 4
Knight_offset = [72, 56]
Knight_data = [Knight_size, Knight_scale, Knight_offset]
Assassin_size = 288
Assassin_scale = 3
Assassin_offset = [112, 107]
Assassin_data =[ Assassin_size, Assassin_scale, Assassin_offset]
#load background image
bg_image = pygame.image.load("G1/Assets/Bg.png").convert_alpha()
#load spritesheets
Knight_sheet = pygame.image.load("G1/Assets/Knight/Sprites.png").convert_alpha()
Assassin_sheet = pygame.image.load("G1/Assets/Assassin/Sprites.png").convert_alpha()
#load vicory image
victory_img = pygame.image.load("G1/Assets/victory.png").convert_alpha()
#define number of steps in each animation
Knight_steps=[8, 8, 20, 8, 11, 19, 10, 6, 13]
Assassin_steps=[8, 8, 6, 6, 8, 18, 7, 6, 19]
#Font
count_font = pygame.font.Font("G1/assets/fonts/turok.ttf", 80)
score_font = pygame.font.Font("G1/assets/fonts/turok.ttf", 30)
#Text
def draw_text(text, font, text_col, x, y):
img = font.render(text, True, text_col)
s.blit(img, (x, y))
#Background
def draw_bg():
scaled_bg = pygame.transform.scale(bg_image, (swidth, sheight))
s.blit(scaled_bg, (0, 0))
#Health bars
red=(255, 0, 0)
yellow=(255, 255, 0)
white=(255, 255, 255)
def draw_health_bar(health, x, y):
ratio = health / 100
pygame.draw.rect(s, white, (x - 2, y - 2, 404, 34))
pygame.draw.rect(s, red, (x, y, 400, 30))
pygame.draw.rect(s, yellow, (x, y, 400 * ratio, 30))
#Player avatars
Knight=Characters(1, 200, 310, False, Knight_data, Knight_sheet, Knight_steps)
Assassin=Characters(2, 700, 310, True, Assassin_data, Assassin_sheet, Assassin_steps)
#game loop
run = True
while run:
clock.tick(FPS)
#Display background
draw_bg()
#Display health bar
draw_health_bar(Knight.health, 20, 20)
draw_health_bar(Assassin.health, 580, 20)
draw_text("P1: " + str(score[0]), score_font, red, 20, 60)
draw_text("P2: " + str(score[1]), score_font, red, 580, 60)
#countdown
if intro_count <= 0:
#Move fighters
Knight.move(swidth, sheight, s, Assassin, round_over)
Assassin.move(swidth, sheight, s, Knight, round_over)
else:
#Display count timer
draw_text(str(intro_count), count_font, red, swidth/2, sheight/3)
#update count timer
if (pygame.time.get_ticks()-last_count_update)>= 1000:
intro_count -= 1
last_count_update = pygame.time.get_ticks()
#Update fighters
Knight.update()
Assassin.update()
#Display fighters
Knight.draw(s)
Assassin.draw(s)
#check for player defeat
if round_over == False:
if Knight.alive == False:
score[1] += 1
round_over = True
round_over_time = pygame.time.get_ticks()
elif Assassin.alive == False:
score[0] += 1
round_over = True
round_over_time = pygame.time.get_ticks()
else:
#display victory image
s.blit(victory_img, (360, 150))
if pygame.time.get_ticks()-round_over_time>round_cooldown:
round_over = False
intro_count = 3
Knight= Knight(1, 200, 310, False, Knight_data, Knight_sheet, Knight_steps)
Assassin= Assassin(2, 700, 310, True, Assassin_data, Assassin_sheet, Assassin_steps)
#event handler
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
#update display
pygame.display.update()
#exit pygame
pygame.quit()`
My Module-
import pygame
class Characters():
def __init__(self, player, x, y, flip, data, sheet, steps):
self.player = player
self.size = data[0]
self.image_scale = data[1]
self.offset = data[2]
self.flip = flip
self.animation_list = self.load_images(sheet, steps)
self.action = 0#0:idle #1:run #2:jump #3:attack1 #4: attack2 #5:hit #6:death
self.frame_index = 0
self.image = self.animation_list[self.action][self.frame_index]
self.update_time = pygame.time.get_ticks()
self.rect = pygame.Rect((x, y, 80, 180))
self.vel_y = 0
self.running = False
self.jump = False
self.attacking = False
self.attack_type = 0
self.attack_cooldown = 0
self.hit = False
self.health = 100
self.alive = True
def load_images(self, sheet, steps):
#extract images from spritesheet
animation_list = []
for y, animation in enumerate(steps):
temp_img_list = []
for x in range(animation):
temp_img = sheet.subsurface(x * self.size, y * self.size, self.size, self.size)
temp_img_list.append(pygame.transform.scale(temp_img, (self.size * self.image_scale, self.size * self.image_scale)))
animation_list.append(temp_img_list)
return animation_list
def move(self, screen_width, screen_height, surface, target, round_over):
SPEED = 10
GRAVITY = 2
dx = 0
dy = 0
self.running = False
self.attack_type = 0
#get keypresses
key = pygame.key.get_pressed()
#can only perform other actions if not currently attacking
if self.attacking == False and self.alive == True and round_over == False:
#check player 1 controls
if self.player == 1:
#movement
if key[pygame.K_a]:
dx = -SPEED
self.running = True
if key[pygame.K_d]:
dx = SPEED
self.running = True
#jump
if key[pygame.K_w] and self.jump == False:
self.vel_y = -30
self.jump = True
#attack
if key[pygame.K_r] or key[pygame.K_t]:
self.attack(target)
#determine which attack type was used
if key[pygame.K_r]:
self.attack_type = 1
if key[pygame.K_t]:
self.attack_type = 2
#check player 2 controls
if self.player == 2:
#movement
if key[pygame.K_LEFT]:
dx = -SPEED
self.running = True
if key[pygame.K_RIGHT]:
dx = SPEED
self.running = True
#jump
if key[pygame.K_UP] and self.jump == False:
self.vel_y = -30
self.jump = True
#attack
if key[pygame.K_KP1] or key[pygame.K_KP2]:
self.attack(target)
#determine which attack type was used
if key[pygame.K_KP1]:
self.attack_type = 1
if key[pygame.K_KP2]:
self.attack_type = 2
#apply gravity
self.vel_y += GRAVITY
dy += self.vel_y
#ensure player stays on screen
if self.rect.left + dx < 0:
dx = -self.rect.left
if self.rect.right + dx > screen_width:
dx = screen_width - self.rect.right
if self.rect.bottom + dy > screen_height - 220:
self.vel_y = 0
self.jump = False
dy = screen_height - 220 - self.rect.bottom
#ensure players face each other
if target.rect.centerx > self.rect.centerx:
self.flip = False
else:
self.flip = True
#apply attack cooldown
if self.attack_cooldown > 0:
self.attack_cooldown -= 1
#update player position
self.rect.x += dx
self.rect.y += dy
#handle animation updates
def update(self):
#check what action the player is performing
if self.health <= 0:
self.health = 0
self.alive = False
self.update_action(6)#6:death
elif self.hit == True:
self.update_action(5)#5:hit
elif self.attacking == True:
if self.attack_type == 1:
self.update_action(3)#3:attack1
elif self.attack_type == 2:
self.update_action(4)#4:attack2
elif self.jump == True:
self.update_action(2)#2:jump
elif self.running == True:
self.update_action(1)#1:run
else:
self.update_action(0)#0:idle
animation_cooldown = 50
#update image
self.image = self.animation_list[self.action][self.frame_index]
#check if enough time has passed since the last update
if pygame.time.get_ticks() - self.update_time > animation_cooldown:
self.frame_index += 1
self.update_time = pygame.time.get_ticks()
#check if the animation has finished
if self.frame_index >= len(self.animation_list[self.action]):
#if the player is dead then end the animation
if self.alive == False:
self.frame_index = len(self.animation_list[self.action]) - 1
else:
self.frame_index = 0
#check if an attack was executed
if self.action == 3 or self.action == 4:
self.attacking = False
self.attack_cooldown = 20
#check if damage was taken
if self.action == 5:
self.hit = False
#if the player was in the middle of an attack, then the attack is stopped
self.attacking = False
self.attack_cooldown = 20
def attack(self, target):
if self.attack_cooldown == 0:
#execute attack
self.attacking = True
self.attack_sound.play()
attacking_rect = pygame.Rect(self.rect.centerx - (2 * self.rect.width * self.flip), self.rect.y, 2 * self.rect.width, self.rect.height)
if attacking_rect.colliderect(target.rect):
target.health -= 10
target.hit = True
def update_action(self, new_action):
#check if the new action is different to the previous one
if new_action != self.action:
self.action = new_action
#update the animation settings
self.frame_index = 0
self.update_time = pygame.time.get_ticks()
def draw(self, surface):
img = pygame.transform.flip(self.image, self.flip, False)
surface.blit(img, (self.rect.x - (self.offset[0] * self.image_scale), self.rect.y - (self.offset[1] * self.image_scale)))
The error occurred-
File "c:\Users\User\Desktop\G1\Battle game V1.py", line 73, in <module>
Knight=Characters(1, 200, 310, False, Knight_data, Knight_sheet, Knight_steps)
File "c:\Users\User\Desktop\G1\Players.py", line 10, in __init__
self.animation_list = self.load_images(sheet, steps)
File "c:\Users\User\Desktop\G1\Players.py", line 33, in load_images
temp_img = sheet.subsurface(x * self.size, y * self.size, self.size, self.size)
ValueError: subsurface rectangle outside surface area
This question already exists:
in my shooting game, my players are positioned on top of my head (player) which is very abnormal and also once the game starts, they start shooting [closed]
Closed 6 months ago.
i have earlier tried to format my question properly but i hope this one is better. am creating a shooter game from https://github.com/russs123/Shooter. however my problem is that my enemies are stacked vertically upwards in a straight line when i run my game and the enemies don't start off at their predefined location. below is the full code i wrote. perhaps if you can run it, it will be better understood.
import pygame, sys
from player import Player
import os
import random
import csv
pygame.init()
screen_width = 600
scroll_thresh = 200
screen_scroll = 0
bg_scroll = 0
screen_height = int(screen_width * 0.8)
screen = pygame.display.set_mode((screen_width, screen_height))
pygame.display.set_caption("Shooter Game")
clock = pygame.time.Clock()
fps = 60
# define game variables
GRAVITY = 0.75
level = 1
ROWS = 16
COLS = 150
TILE_SIZE = screen_height // ROWS
TILE_TYPES = 21
img_list = []
for x in range(TILE_TYPES):
img = pygame.image.load(f"img/tile/{x}.png")
img = pygame.transform.scale(img, (TILE_SIZE, TILE_SIZE))
img_list.append(img)
# color variables
bg = (144, 201, 120)
RED = (255, 0, 0)
WHITE = (255, 255, 255)
GREEN = (0, 255, 0)
BLACK = (0, 0, 0)
# define player action variables
moving_left = False
moving_right = False
shoot = False
grenade = False
grenade_thrown = False
# load up images
pine1_img = pygame.image.load("img/Background/pine1.png").convert_alpha()
pine2_img = pygame.image.load("img/Background/pine2.png").convert_alpha()
mountain_img = pygame.image.load("img/Background/mountain.png").convert_alpha()
sky_cloud_img = pygame.image.load("img/Background/sky_cloud.png").convert_alpha()
bullet_img = pygame.image.load("img/icons/bullet.png").convert_alpha()
grenade_img = pygame.image.load("img/icons/grenade.png").convert_alpha()
# pick up boxes
health_box_img = pygame.image.load("img/icons/health_box.png").convert_alpha()
ammo_box_img = pygame.image.load("img/icons/ammo_box.png").convert_alpha()
grenade_box_img = pygame.image.load("img/icons/grenade_box.png").convert_alpha()
# name_dt = type(name)
item_boxes = {
"Health": health_box_img,
"Ammo": ammo_box_img,
"Grenade": grenade_img,
}
# define fonts
font = pygame.font.SysFont("Futura", 30)
def draw_text(text, font, text_col, x, y):
img = font.render(text, True, text_col)
screen.blit(img, (x, y))
def draw_bg():
screen.fill(bg)
screen.blit(sky_cloud_img, (0, 0))
screen.blit(mountain_img, (0, screen_height - mountain_img.get_height() - 300))
screen.blit(pine1_img, (0, screen_height - pine1_img.get_height() - 150))
screen.blit(pine2_img, (0, screen_height - pine2_img.get_height()))
class Soldier(pygame.sprite.Sprite):
def __init__(self, char_type, x, y, scale, speed, ammo, grenades):
pygame.sprite.Sprite.__init__(self)
self.alive = True
self.char_type = char_type
self.speed = speed
self.ammo = ammo
self.start_ammo = ammo
self.shoot_cooldown = 0
self.grenades = grenades
self.health = 100
self.max_health = self.health
self.direction = 1
self.vel_y = 0
self.jump = False
self.in_air = True
self.flip = False
self.animation_list = []
self.frame_index = 0
self.action = 0
# ai specific variables
self.move_counter = 0
self.vision = pygame.Rect(0, 0, 150, 20)
self.idling = 0
self.idling_counter = 0
self.update_time = pygame.time.get_ticks()
# load all images for the players
animation_types = ["idle", "run", "jump", "death"]
for animation in animation_types:
temp_list = []
# reset temporary list of images
# count number of files in the folder
num_of_frames = len(os.listdir(f"img/{self.char_type}/{animation}"))
for i in range(num_of_frames):
img = pygame.image.load(f"img/{self.char_type}/{animation}/{i}.png").convert_alpha()
img = pygame.transform.scale(img, (int(img.get_width() * scale), int(img.get_height() * scale)))
temp_list.append(img)
self.animation_list.append(temp_list)
self.image = self.animation_list[self.action][self.frame_index]
self.rect = self.image.get_rect()
self.rect.center = (x, y)
self.width = self.image.get_width()
self.height = self.image.get_height()
def update(self):
self.update_animation()
self.check_alive()
# update cooldown
if self.shoot_cooldown > 0:
self.shoot_cooldown -= 1
def move(self, moving_left, moving_right):
screen_scroll = 0
dx = 0
dy = 0
if moving_left:
dx = -self.speed
self.flip = True
self.direction = -1
if moving_right:
dx = self.speed
self.flip = False
self.direction = 1
if self.jump == True and self.in_air == False:
self.vel_y = -11
self.jump = False
self.in_air = True
# apply gravity
self.vel_y += GRAVITY
if self.vel_y > 10:
self.vel_y
dy += self.vel_y
# check for collision
for tile in world.obstacle_list:
# check collision in the x direction
if tile[1].colliderect(self.rect.x + dx, self.rect.y, self.width, self.height):
dx = 0
# check for collision in the y direction
if tile[1].colliderect(self.rect.x, self.rect.y + dy, self.width, self.height):
# check if below the ground, i.e jumping
if self.vel_y < 0:
self.vel_y = 0
dy = tile[1].bottom - self.rect.top
# check if above the ground, ie falling
elif self.vel_y >= 0:
self.vel_y = 0
self.in_air = False
dy = tile[1].top - self.rect.bottom
self.rect.x += dx
self.rect.y += dy
# update scroll based on player position
if self.char_type == "player":
if self.rect.right > screen_width - scroll_thresh or self.rect.left < scroll_thresh:
self.rect.x = -dx
screen_scroll = -dx
return screen_scroll
def shoot(self):
if self.shoot_cooldown == 0 and self.ammo > 0:
self.shoot_cooldown = 20
bullet = Bullet(self.rect.centerx + (0.75 * self.rect.size[0] * self.direction), self.rect.centery,
self.direction)
bullet_group.add(bullet)
# reduce ammo after each shot
self.ammo -= 1
def ai(self):
if self.alive and player.alive:
if self.idling == False and random.randint(1, 200) == 1:
self.update_action(0)
self.idling = True
self.idling_counter = 50
# check if ai is near the player
if self.vision.colliderect(player.rect):
# stop running and face the player
self.update_action(0)
self.shoot()
else:
if self.idling == False:
if self.direction == 1:
ai_moving_right = True
else:
ai_moving_right = False
ai_moving_left = not ai_moving_right
self.move(ai_moving_left, ai_moving_right)
self.update_action(1)
self.move_counter += 1
# update ai vision as the enemy moves
self.vision.center = (self.rect.centerx + 75 * self.direction, self.rect.centery)
if self.move_counter > TILE_SIZE:
self.direction *= -1
self.move_counter *= -1
else:
self.idling_counter -= 1
if self.idling_counter <= 0:
self.idling = False
# scroll
self.rect.x = screen_scroll
def update_animation(self):
ANIMATION_COOLDOWN = 100
# update image depending on current index
self.image = self.animation_list[self.action][self.frame_index]
# check if enough time has passed since the last update
if pygame.time.get_ticks() - self.update_time > ANIMATION_COOLDOWN:
self.update_time = pygame.time.get_ticks()
self.frame_index += 1
# if animation has run out then restart to the first
if self.frame_index >= len(self.animation_list[self.action]):
if self.action == 3:
self.frame_index = len(self.animation_list[self.action]) - 1
else:
self.frame_index = 0
def check_alive(self):
if self.health <= 0:
self.health = 0
self.speed = 0
self.alive = False
self.update_action(3)
def update_action(self, new_action):
# check if new action is different from the previous one
if new_action != self.action:
self.action = new_action
# update animation settings
self.frame_index = 0
self.update_time = pygame.time.get_ticks()
def draw(self):
screen.blit(pygame.transform.flip(self.image, self.flip, False), self.rect)
class HealthBar():
def __init__(self, health, x, y, max_health):
self.x = x
self.y = y
self.health = health
self.max_health = max_health
def draw(self, health):
self.health = health
pygame.draw.rect(screen, BLACK, (self.x - 2, self.y - 2, 154, 24))
pygame.draw.rect(screen, RED, (self.x, self.y, 150, 20))
ratio = self.health / self.max_health
pygame.draw.rect(screen, GREEN, (self.x, self.y, 150 * ratio, 20))
class World():
def __init__(self):
self.obstacle_list = []
def process_data(self, data):
for y, row in enumerate(data):
for x, tile in enumerate(row):
if tile >= 0:
img = img_list[tile]
img_rect = img.get_rect()
img_rect.x = x * TILE_SIZE
img_rect.y = y * TILE_SIZE
tile_data = (img, img_rect)
if 0 <= tile <= 8:
self.obstacle_list.append(tile_data)
elif 9 <= tile <= 10:
# water
water = Water(img, x * TILE_SIZE, y * TILE_SIZE, )
water_group.add(water)
pass
elif 11 <= tile <= 14:
# decoration
decoration = Decoration(img, x * TILE_SIZE, y * TILE_SIZE)
decoration_group.add(decoration)
elif tile == 15:
# create a player
player = Soldier("player", x * TILE_SIZE, y * TILE_SIZE, 1.65, 5, 20, 5)
health_bar = HealthBar(10, 10, player.health, player.health)
elif tile == 16:
# create enemy
enemy = Soldier("enemy", x * TILE_SIZE, y * TILE_SIZE, 1.65, 2, 20, 0)
enemy_group.add(enemy)
elif tile == 17:
# create ammo box
item_box = ItemBox("Ammo", x * TILE_SIZE, y * TILE_SIZE)
item_box_group.add(item_box)
elif tile == 18:
# create grenade box
item_box = ItemBox("Grenade", x * TILE_SIZE, y * TILE_SIZE)
item_box_group.add(item_box)
elif tile == 19:
# create health box
item_box = ItemBox("Health", x * TILE_SIZE, y * TILE_SIZE)
item_box_group.add(item_box)
elif tile == 20:
# create exit point
exit = Exit(img, x * TILE_SIZE, y * TILE_SIZE, )
exit_group.add(exit)
return player, health_bar
def draw(self):
for tile in self.obstacle_list:
tile[1][0] += screen_scroll
screen.blit(tile[0], tile[1])
class Decoration(pygame.sprite.Sprite):
def __init__(self, img, x, y):
pygame.sprite.Sprite.__init__(self)
self.image = img
self.rect = self.image.get_rect()
self.rect.midtop = (x + TILE_SIZE // 2, y + (TILE_SIZE - self.image.get_height()))
def update(self):
self.rect.x += screen_scroll
class Water(pygame.sprite.Sprite):
def __init__(self, img, x, y):
pygame.sprite.Sprite.__init__(self)
self.image = img
self.rect = self.image.get_rect()
self.rect.midtop = (x + TILE_SIZE // 2, y + (TILE_SIZE - self.image.get_height()))
def update(self):
self.rect.x += screen_scroll
class Exit(pygame.sprite.Sprite):
def __init__(self, img, x, y):
pygame.sprite.Sprite.__init__(self)
self.image = img
self.rect = self.image.get_rect()
self.rect.midtop = (x + TILE_SIZE // 2, y + (TILE_SIZE - self.image.get_height()))
class ItemBox(pygame.sprite.Sprite):
def __init__(self, item_type, x, y):
pygame.sprite.Sprite.__init__(self)
self.item_type = item_type
self.image = item_boxes[self.item_type]
self.rect = self.image.get_rect()
self.rect.midtop = (x + TILE_SIZE // 2, y + (TILE_SIZE - self.image.get_height()))
def update(self):
# scroll
self.rect.x += screen_scroll
# check if player has picked up the box
if pygame.sprite.collide_rect(self, player):
# check what kind of box it was
if self.item_type == "Health":
player.health += 25
if player.health > player.max_health:
player.health = player.max_health
elif self.item_type == "Ammo":
player.ammo += 15
elif self.item_type == "Grenade":
player.grenades += 3
# delete the item box
self.kill()
class Bullet(pygame.sprite.Sprite):
def __init__(self, x, y, direction):
pygame.sprite.Sprite.__init__(self)
self.speed = 10
self.image = bullet_img
self.rect = self.image.get_rect()
self.rect.center = (x, y)
self.direction = direction
def update(self):
self.rect.x += self.direction * self.speed
# check if bullet has left the screen
if self.rect.right < 0 and self.rect.left > screen_width:
self.kill()
# check for collision with level
for tile in world.obstacle_list:
if tile[1].colliderect(self.rect):
self.kill()
# check collision with characters
if pygame.sprite.spritecollide(player, bullet_group, False):
if player.alive:
player.health -= 5
self.kill()
for enemy in enemy_group:
if pygame.sprite.spritecollide(enemy, bullet_group, False):
if enemy.alive:
enemy.health -= 25
self.kill()
class Grenade(pygame.sprite.Sprite):
def __init__(self, x, y, direction):
pygame.sprite.Sprite.__init__(self)
self.timer = 100
self.vel_y = -11
self.speed = 7
self.image = grenade_img
self.rect = self.image.get_rect()
self.rect.center = (x, y)
self.direction = direction
self.width = self.image.get_width()
self.height = self.image.get_height()
def update(self):
self.vel_y += GRAVITY
dx = self.direction * self.speed
dy = self.vel_y
# check for collision with level
for tile in world.obstacle_list:
# check if grenade has hit a wall
if tile[1].colliderect(self.rect.x + dx, self.rect.y, self.width, self.height):
self.direction *= -1
dx = self.direction * self.speed
if tile[1].colliderect(self.rect.x, self.rect.y + dy, self.width, self.height):
self.speed = 0
# check if below the ground, i.e thrown
if self.vel_y < 0:
self.y = 0
dy = tile[1].bottom - self.rect.top
# check if above the ground, ie falling
elif self.vel_y >= 0:
self.vel_y = 0
dy = tile[1].top - self.rect.bottom
# update grenade position
self.rect.x += dx
self.rect.y += dy
# explosion countdown
self.timer -= 1
if self.timer <= 0:
self.kill()
explosion = Explosion(self.rect.x, self.rect.y, 0.5)
explosion_group.add(explosion)
# do damage to anyone nearby
if abs(self.rect.centerx - player.rect.centerx) < TILE_SIZE * 2 and \
abs(self.rect.centery - player.rect.centery) < TILE_SIZE * 2:
player.health -= 50
for enemy in enemy_group:
if abs(self.rect.centerx - enemy.rect.centerx) < TILE_SIZE * 2 and \
abs(self.rect.centery - enemy.rect.centery) < TILE_SIZE * 2:
enemy.health -= 50
class Explosion(pygame.sprite.Sprite):
def __init__(self, x, y, scale):
pygame.sprite.Sprite.__init__(self)
self.images = []
for num in range(1, 6):
img = pygame.image.load(f"img/explosion/exp{num}.png").convert_alpha()
img = pygame.transform.scale(img, (int(img.get_width() * scale), (int(img.get_height() * scale))))
self.images.append(img)
self.frame_index = 0
self.image = self.images[self.frame_index]
self.rect = self.image.get_rect()
self.rect.center = (x, y)
self.counter = 0
def update(self):
EXPLOSION_SPEED = 4
# update explosion animation
self.counter += 1
if self.counter >= EXPLOSION_SPEED:
self.counter = 0
self.frame_index += 1
# if animation is complete, then delete the explosion
if self.frame_index >= len(self.images):
self.kill()
else:
self.image = self.images[self.frame_index]
# create sprite groups
enemy_group = pygame.sprite.Group()
bullet_group = pygame.sprite.Group()
grenade_group = pygame.sprite.Group()
explosion_group = pygame.sprite.Group()
item_box_group = pygame.sprite.Group()
decoration_group = pygame.sprite.Group()
water_group = pygame.sprite.Group()
exit_group = pygame.sprite.Group()
# create empty tile list
world_data = []
for row in range(ROWS):
r = [-1] * COLS
world_data.append(r)
# load in level data and create world
with open(f"level{level}_data.csv", newline="") as csvfile:
reader = csv.reader(csvfile, delimiter=",")
for x, row in enumerate(reader):
for y, tile in enumerate(row):
world_data[x][y] = int(tile)
print(world_data)
world = World()
player, health_bar = world.process_data(world_data)
run = True
while run:
clock.tick(fps)
draw_bg()
world.draw()
health_bar.draw(player.health)
# show ammo
draw_text("AMMO:", font, WHITE, 10, 35)
for x in range(player.ammo):
screen.blit(bullet_img, (90 + (x * 10), 40))
# show grenade
draw_text("GRENADES: ", font, WHITE, 10, 65)
for x in range(player.grenades):
screen.blit(grenade_img, (130 + (x * 15), 66))
player.update()
player.draw()
for enemy in enemy_group:
enemy.ai()
enemy.update()
enemy.draw()
# update and draw groups
bullet_group.update()
grenade_group.update()
explosion_group.update()
item_box_group.update()
decoration_group.update()
water_group.update()
exit_group.update()
bullet_group.draw(screen)
grenade_group.draw(screen)
explosion_group.draw(screen)
item_box_group.draw(screen)
decoration_group.draw(screen)
water_group.draw(screen)
exit_group.draw(screen)
# update player actions, 1 is run, 0 = idle, 2 = in air
if player.alive:
# shoot bullet
if shoot:
player.shoot()
elif grenade and grenade_thrown == False and player.grenades > 0:
grenade = Grenade(player.rect.centerx + (0.5 * player.rect.size[0] * player.direction),
player.rect.top, player.direction)
grenade_group.add(grenade)
# reduce grenades
player.grenades -= 1
grenade_thrown = True
if player.in_air:
player.update_action(2)
elif moving_left or moving_right:
player.update_action(1)
else:
player.update_action(0)
screen_scroll = player.move(moving_left, moving_right)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
# keyboard presses
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_a:
moving_left = True
if event.key == pygame.K_d:
moving_right = True
if event.key == pygame.K_SPACE:
shoot = True
if event.key == pygame.K_q:
grenade = True
if event.key == pygame.K_w and player.alive:
player.jump = True
if event.key == pygame.K_ESCAPE:
run = False
# keyboard button released
if event.type == pygame.KEYUP:
if event.key == pygame.K_a:
moving_left = False
if event.key == pygame.K_d:
moving_right = False
if event.key == pygame.K_SPACE:
shoot = False
if event.key == pygame.K_q:
grenade = False
grenade_thrown = False
pygame.display.update()
pygame.quit()
i have looked at this code for days but cant seem to find out the problem exactly. so, the question once again is how to properly arrange the enemies on the screen at their various predefined positions and not directly on top of my player.
I have a variable called left and it should turn to true when I hit the left arrow key but it doesn't seem to switch to true. It should also call the sprite walking left animation as a result of left turning true but obviously that isn't working I just need to know why the variable won't turn to true.
import pygame
import random
import math
pygame.init()
screenwidth = 500
screenheight = 500
win = pygame.display.set_mode((screenwidth, screenheight))
pygame.display.set_caption('First Game')
bkg = pygame.image.load('2.jpg')
char1 = pygame.image.load('guy.png')
char1 = pygame.transform.scale(char1, (100, 100))
walkRight = []
walkLeft = []
Howmany = 4
for i in range(1, 13):
walkRight.append(pygame.transform.scale(pygame.image.load('R' + str(i) + '.png'), (100, 100)))
for i in range(1, 13):
walkLeft.append(pygame.transform.scale(pygame.image.load('L' + str(i) + '.png'), (100, 100)))
GameO = pygame.image.load('GO.jpg')
rock = pygame.image.load('b.png')
rock = pygame.transform.scale(rock, (100, 100))
clock = pygame.time.Clock()
class player(object):
def __init__(self, x, y, width, height):
self.x = x
self.y = y
self.width = width
self.height = height
self.GameOver = False
self.vel = 10
self.walkCount = 0
self.left = False
self.right = False
self.lives = 3
self.hit = 0
self.hit1 = False
def draw(self, win):
if self.walkCount + 1 >= 27:
self.walkCount = 0
if self.left == True:
win.blit(walkLeft[self.walkCount // 3], (self.x, self.y))
self.walkCount += 1
print ("hey we should be walking left right now ")
pygame.display.update()
elif self.right == True :
win.blit(walkRight[self.walkCount // 3], (self.x, self.y))
self.walkCount += 1
else:
win.blit(char1, (self.x, self.y))
class rocky():
def __init__(self):
self.x = random.randrange(0, 430)
self.y = -100
def draw(self, win):
win.blit(rock, (self.x, self.y))
def redrawgamewindow():
win.blit(bkg, (0, 0))
man.draw(win)
rock1.draw(win)
pygame.display.flip()
def collided (rockx, rocky, manx, many):
man.hit = 0
distance = math.sqrt((math.pow(rockx-manx, 2) + (math.pow(rocky-many, 2))))
if distance < 75:
man.hit += 1
print("we be touched")
man.hit1 = True
else:
man.hit1 = False
my_list= []
for number in range(Howmany):
my_object = rocky()
my_list.append(my_object)
rock1 = rocky()
man = player(250, 400, 100, 100)
run = True
while run:
print (man.left)
# Setting fps
clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
run = False
# Getting keys pressed
keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT] and man.x > 0:
man.x -= man.vel
man.left = True
man.right = False
elif keys[pygame.K_RIGHT] and man.x < 500 - man.vel - man.width:
man.x += man.vel
man.left = False
man.right = True
for rockk in my_list:
rock1.draw(win)
else:
man.left = False
man.right = False
man.walkCount = 0
rock1.y += 5
if rock1.y >= 500:
rock1.x = random.randrange(0, 430)
rock1.y = -100
if man.hit1 == True:
rock1.x = random.randrange(0, 430)
rock1.y = -100
if man.hit == 1:
man.lives -=1
if man.hit ==2:
man.lives -=1
if man.lives <= 0:
print("THE GAME IS OVER ")
exit()
collided(rock1.x, rock1.y, man.x, man.y)
redrawgamewindow()
win.blit(pygame.image.load('R1.png').convert_alpha(), (200, 200))
You have misplaced the else case. You accidentally put the else case at the end of for loop (else clause) and not after the if-elif statement:
if keys[pygame.K_LEFT] and man.x > 0:
man.x -= man.vel
man.left = True
man.right = False
elif keys[pygame.K_RIGHT] and man.x < 500 - man.vel - man.width:
man.x += man.vel
man.left = False
man.right = True
# INSERT
else:
man.left = False
man.right = False
man.walkCount = 0
for rockk in my_list:
rock1.draw(win)
# DELETE
#else:
# man.left = False
# man.right = False
# man.walkCount = 0
I am trying to get my pieces to collide and and when I jump up into the air the characters should not collide.
Here is a video explaining the problem:
https://drive.google.com/file/d/1a26Vmd6TF4C3dJ0DpnFLTR1d3a_lEfn4/view?usp=sharing
The collision is with the goblin.
Furthermore, we can see that the goblin is colliding even though the boxes aren't touching and when on top of the hitbox.
I have tried to change the condition of the loop for example changed the ">" around to "<" and tried making the jump higher. Both of these did not resolve the problem and I am not an experienced coder.
Here is the main problem:
if (adventurer.hitbox_running[0] > attacker.hitbox[0] and adventurer.hitbox_running[0] < attacker.hitbox[0]+70) or (adventurer.hitbox_running[0]+70 > attacker.hitbox[0] and adventurer.hitbox_running[0]+90 < attacker.hitbox[0]+70):
if (adventurer.hitbox_running[1] > attacker.hitbox[1] and adventurer.hitbox_running[1] < attacker.hitbox[1]+70) or (adventurer.hitbox_running[1]+90 > attacker.hitbox[1] and adventurer.hitbox_running[1]+90 < attacker.hitbox[1]+70):
window.fill((255,255,255))
death()
pygame.display.update()
s(0.1)
print("hit")
Here is the entire code with all of the classes and everything:
from time import sleep as s
import random
import pygame
import time
#Loads and plays the music
pygame.mixer.pre_init(44100,16,2,4096)
pygame.init()
pygame.mixer.music.load("Music.mp3")
pygame.mixer.music.set_volume(0.0)
pygame.mixer.music.play(-1)
score = 0
#sets the dimension of the window and loads in the background
window = pygame.display.set_mode((1000, 500))
pygame.display.set_caption("Practice Game")
background = pygame.image.load('pixel6.png')
#Transforms the background to desired dimensions
background = pygame.transform.scale(background, (1000, 500))
#Loads all the jump animation
jumpv1 = [pygame.image.load('adventurer-jump-00.png'),pygame.image.load('adventurer-jump-01.png'),pygame.image.load('adventurer-jump-02.png'),pygame.image.load('adventurer-jump-03.png'), pygame.image.load('adventurer-smrslt-00.png'),pygame.image.load('adventurer-smrslt-01.png'),pygame.image.load('adventurer-smrslt-02.png'),pygame.image.load('adventurer-smrslt-03.png')]
jumpv2 = [pygame.image.load('adventurer-smrslt-00.png'),pygame.image.load('adventurer-smrslt-01.png'),pygame.image.load('adventurer-smrslt-02.png'),pygame.image.load('adventurer-smrslt-03.png')]
jumpv3 = [pygame.image.load('adventurer-smrslt-00.png'),pygame.image.load('adventurer-smrslt-01.png'),pygame.image.load('adventurer-smrslt-02.png'),pygame.image.load('adventurer-smrslt-03.png')]
jumpv4 = [pygame.image.load('adventurer-smrslt-00.png'),pygame.image.load('adventurer-smrslt-01.png'),pygame.image.load('adventurer-smrslt-02.png'),pygame.image.load('adventurer-smrslt-03.png')]
jump = jumpv1+jumpv2+jumpv3+jumpv4
#running animation
run = [pygame.image.load('adventurer-run-00.png'), pygame.image.load('adventurer-run-01.png'),pygame.image.load('adventurer-run-02.png'),pygame.image.load('adventurer-run-03.png')]
#sliding animation
slide = [pygame.image.load('adventurer-slide-00.png'),pygame.image.load('adventurer-slide-01.png'),pygame.image.load('adventurer-stand-00.png'),pygame.image.load('adventurer-stand-01.png'),pygame.image.load('adventurer-stand-02.png')]
#attacking animation
firstattack = [pygame.image.load('adventurer-attack3-00.png'),pygame.image.load('adventurer-attack3-01.png'),pygame.image.load('adventurer-attack3-02.png'),pygame.image.load('adventurer-attack3-03.png'),pygame.image.load('adventurer-attack3-04.png'),pygame.image.load('adventurer-attack3-05.png')]
secondattack = [pygame.image.load('adventurer-attack2-00.png'),pygame.image.load('adventurer-attack2-01.png'),pygame.image.load('adventurer-attack2-02.png'),pygame.image.load('adventurer-attack2-03.png'),pygame.image.load('adventurer-attack2-04.png'),pygame.image.load('adventurer-attack2-05.png')]
thirdattack = [pygame.image.load('adventurer-attack1-00.png'),pygame.image .load('adventurer-attack1-01.png'),pygame.image.load('adventurer-attack1-02.png'),pygame.image.load('adventurer-attack1-03.png'), pygame.image.load('adventurer-attack1-04.png')]
attack = firstattack+secondattack+ thirdattack
#falling animation
falling = [pygame.image.load('adventurer-fall-00.png'), pygame.image.load('adventurer-fall-01.png')]
score = 0
run_program = True
#resizes all the adventuruer images to specified dimensions
for i in range (20):
jump[i] = pygame.transform.scale(jump[i],(90,90))
for i in range(3):
run[i] = pygame.transform.scale(run[i],(90,90))
for i in range (4):
slide[i] = pygame.transform.scale(slide[i],(90,90))
for i in range (1):
falling[i] = pygame.transform.scale(falling[i],(90,90))
for i in range(16):
attack[i] = pygame.transform.scale(attack[i],(90,90))
background_x = 0
background_2 = background.get_width()
clock = pygame.time.Clock()
ghost_image = pygame.image.load('imgg.png')
def text_objects(text, font):
textSurface = font.render(text, True, (0,0,0))
return textSurface, textSurface.get_rect()
def message_display(text):
largeText = pygame.font.Font('freesansbold.ttf',115)
TextSurf, TextRect = text_objects(text, largeText)
TextRect.center = ((1000/2),(500/2))
window.blit(TextSurf, TextRect)
pygame.display.update()
def death():
message_display('You DIED')
class ghost(object):
ghost_animation = [pygame.image.load('imgg.png'),pygame.image.load('imgg.png')]
def __init__(self, x,y,height):
self.x = x
self.y =y
self.height = height
self.hitbox = (x,y,100,100)
self.count = 0
def draw(self, window):
self.hitbox = (self.x, self.y, 45, 60)
if self.count >=1:
self.count = 0
self.count +=1
window.blit(pygame.transform.scale(self.ghost_animation[self.count], (45,60)), (self.x, self.y))
pygame.draw.rect(window, (255,0,0), self.hitbox, 2)
def hit(self):
print ("hit")
class eye(object):
eye_load = pygame.image.load('obstc2.png')
def __init__(self, x,y,width2, height2):
self.x = x
self.y =y
self.hitbox_enemy = (x,y,200,100)
self.count1 = 0
def draw(self, window):
self.hitbox_enemy = (self.x, self.y, 65, 65)
window.blit(pygame.transform.scale(self.eye_load, (65,65)), (self.x, self.y))
pygame.draw.rect(window, (255,0,0), self.hitbox_enemy, 2)
class player(object):
def __init__(self, x,y):
self.vel = 0.5
self.running = True
self.jumping = True
self.sliding = True
self.attacking = True
self.isJump = False
self. jumps = True
self.fall = True
self.player_x = 40
self.player_y = 378
self.x = 40
self.y = 378
self.width = 378
self.speed = 0.6
self.jumpcount = 10
self.jumpingcount = 0
self.runcount = 0
self.attackcount = 0
self.slidecount = 0
self.fallspeed = 0.3
self.fallingcount = 0
self.hitbox_running = (self.player_x,self.player_y,90,90)
self.hitbox_sliding = (45,self.player_y+47,65,45)
self.hitbox_falling = (self.player_x+30,self.player_y,35,80)
self.hitbox_jumping = (self.player_x+20,self.player_y+20,52,55)
self.hitbox_attacking = (58,405,47,70)
self.hitbox_sword = (108, 405, 20, 50)
def movement(self, window):
pygame.time.delay(20)
if self.runcount >= 3:
self.runcount = 0
if self.running == True:
window.blit(run[self.runcount],(int(self.player_x),int(self.player_y)))
self.runcount +=1
self.hitbox_running = (self.player_x+30,self.player_y+20,48,70)
pygame.draw.rect(window,(255,0,0),self.hitbox_running, 2)
if (keys[pygame.K_DOWN]) or ((keys[pygame.K_DOWN]) and keys[pygame.K_p]):
if self.player_y == 378:
self.running = False
if self.slidecount >= 4:
self.slidecount = 0
if self.sliding:
window.blit(slide[self.slidecount],(int(self.player_x),int(self.player_y)))
self.slidecount +=1
pygame.draw.rect(window,(255,0,0),self.hitbox_sliding, 2)
if event.type == pygame.KEYDOWN:
if (event.key == pygame.K_DOWN )and self.player_y < self.width:
self.running = False
self.jumping = False
self.fallspeed += 0.2
if self.fallingcount >= 1:
self.fallingcount = 0
if self.fall:
window.blit(falling[self.fallingcount], (int(self.player_x),int(self.player_y)))
self.hitbox_falling = (self.player_x+30,self.player_y,35,80)
pygame.draw.rect(window,(255,0,0),self.hitbox_falling, 2)
self.fallingcount +=1
if keys[pygame.K_UP] and keys[pygame.K_p] :
self.fallspeed = 0.3
self.running = False
self.jumping = False
self.sliding = False
if self.attackcount >= 16:
self.attackcount = 0
if self.attacking:
window.blit(attack[self.attackcount],(int(self.player_x),int(self.player_y)))
self.attackcount += 1
self.hitbox_attacking = (self.player_x+30,self.player_y+20,38,70)
self.hitbox_sword = (self.player_x+72, self.player_y+20, 20, 50)
pygame.draw.rect(window,(255,0,0),self.hitbox_attacking, 2)
pygame.draw.rect(window,(255,0,0),self.hitbox_sword, 2)
if self.jumpingcount >= 20:
self.jumpingcount = 0
if self.jumping and self.player_y < self.width:
window.blit(jump[self.jumpingcount],(int(self.player_x),int(self.player_y)))
self.hitbox_jumping = (int(self.player_x+20),int(self.player_y+20),52,55)
pygame.draw.rect(window,(255,0,0),self.hitbox_jumping, 2)
self.jumpingcount +=1
self.fallspeed = 0.3
if keys[pygame.K_UP]:
self.fallspeed = 0.3
self.running = False
if self.jumpingcount >= 20:
self.jumpingcount = 0
if self.jumping and self.player_y < self.width:
window.blit(jump[self.jumpingcount],(int(self.player_x),int(self.player_y)))
self.hitbox_jumping = (int(self.player_x+20),int(self.player_y+20),52,55)
pygame.draw.rect(window,(255,0,0),self.hitbox_jumping, 2)
self.jumpingcount +=1
self.fallspeed = 0.3
if keys[pygame.K_p] and not keys[pygame.K_UP]:
self.running = False
self.jumping = False
self.sliding = False
if self.attackcount >= 16:
self.attackcount = 0
if self.attacking:
self.hitbox_attacking = (self.player_x+30,self.player_y+20,38,70)
self.hitbox_sword = (self.player_x+72, self.player_y+20, 20, 50)
window.blit(attack[self.attackcount],(int(self.player_x),int(self.player_y)))
self.attackcount += 1
pygame.draw.rect(window,(255,0,0),self.hitbox_attacking, 2)
pygame.draw.rect(window,(255,0,0),self.hitbox_sword, 2)
if keys[pygame.K_DOWN] and keys[pygame.K_UP]:
self.running = False
if event.type == pygame.KEYUP:
if event.key == pygame.K_DOWN:
self.running = True
self.jumping = True
self.fallspeed = 0.3
if event.key == pygame.K_UP:
self.running=True
if event.key == pygame.K_p:
self.running = True
self.jumping = True
self.sliding = True
class enemy(object):
walkright = [pygame.image.load('R1E.png'), pygame.image.load('R2E.png'), pygame.image.load('R3E.png'), pygame.image.load('R4E.png'), pygame.image.load('R5E.png'), pygame.image.load('R6E.png'), pygame.image.load('R7E.png'), pygame.image.load('R8E.png'), pygame.image.load('R9E.png'), pygame.image.load('R10E.png'), pygame.image.load('R11E.png')]
walkleft = [pygame.image.load('L1E.png'), pygame.image.load('L2E.png'), pygame.image.load('L3E.png'), pygame.image.load('L4E.png'), pygame.image.load('L5E.png'), pygame.image.load('L6E.png'), pygame.image.load('L7E.png'), pygame.image.load('L8E.png'), pygame.image.load('L9E.png'), pygame.image.load('L10E.png'), pygame.image.load('L11E.png')]
for i in range (10):
walkright[i] = pygame.transform.scale(walkright[i],(70,70))
for i in range(10):
walkleft[i] = pygame.transform.scale(walkleft[i],(70,70))
def __init__(self,enemy_x,enemy_y, end):
self.x = enemy_x
self.y = enemy_y
self.end = end
self.path = [self.x,self.end]
self.walkcount = 0
self.vel = 7
self.hitbox = (self.x,self.y-15,90,90)
def draw_enemy(self,window):
self.move()
if self.walkcount+1 >= 33:
self.walkcount = 0
self.vel+=0.2
#walking right
if self.vel > 0:
window.blit(self.walkleft[self.walkcount//3], (self.x,self.y-15))
self.walkcount += 1
#walking left
if self.vel < 0:
## window.blit(self.walkleft[self.walkcount//3], (self.x,self.y))
self.walkcount -= 1
if self.x < -100:
self.x = 1050
self.hitbox = (self.x+25,self.y-15,41,70)
pygame.draw.rect(window, (255,0,0),self.hitbox,2)
def move(self):
if self.vel > 0:
#see if position + movement space is < the end, then it is able to move
if self.x + self.vel < self.path[1]:
self.x -= self.vel
#past end point and turns 180
else:
self.vel = self.vel*-1
self.walkcount = 0
#see if position is smaller than starting position
else:
if self.x - self.vel > self.path[0]:
#vel is already negative
self.x += self.vel
else:
#Truns 180 agian
self.vel = self.vel* -1
self.walkcount = 0
class wizard(object):
walkleft = [pygame.image.load('wizard-fly-forward_04.gif'), pygame.image.load('wizard-fly-forward_04.gif'), pygame.image.load('wizard-fly-forward_04.gif'), pygame.image.load('wizard-fly-forward_04.gif'), pygame.image.load('wizard-fly-forward_04.gif'), pygame.image.load('wizard-fly-forward_05.gif'), pygame.image.load('wizard-fly-forward_04.gif'), pygame.image.load('wizard-fly-forward_04.gif'), pygame.image.load('wizard-fly-forward_05.gif'), pygame.image.load('wizard-fly-forward_04.gif'), pygame.image.load('wizard-fly-forward_04.gif'), pygame.image.load('wizard-fly-forward_04.gif'), pygame.image.load('wizard-fly-forward_05.gif'),pygame.image.load('wizard-fly-forward_04.gif'), pygame.image.load('wizard-fly-forward_04.gif'),pygame.image.load('wizard-fly-forward_05.gif')]
for i in range(16):
walkleft[i] = pygame.transform.scale(walkleft[i],(70,70))
def __init__(self,enemy_x,enemy_y, end):
self.x = enemy_x
self.y = enemy_y
self.end = end
self.path = [self.x,self.end]
self.walkcount = 0
self.vel = 7
self.hitbox = (self.x,self.y-15,90,90)
def draw_enemy(self,window):
self.move()
if self.walkcount >= 16:
self.walkcount = 0
#walking left
if self.vel > 0:
window.blit(self.walkleft[self.walkcount], (self.x,self.y-15))
self.walkcount += 1
self.vel+=0.002
if self.x < -120:
self.x = 1100
self.hitbox = (self.x+25,self.y-15,41,70)
pygame.draw.rect(window, (255,0,0),self.hitbox,2)
def move(self):
if self.vel > 0:
#see if position + movement space is < the end, then it is able to move
if self.x + self.vel < self.path[1]:
self.x -= self.vel
#past end point and turns 180
else:
self.vel = self.vel*-1
self.walkcount = 0
#see if position is smaller than starting position
else:
if self.x - self.vel > self.path[0]:
#vel is already negative
self.x += self.vel
else:
#Truns 180 agian
self.vel = self.vel* -1
self.walkcount = 0
class dragon(object):
walkleft = [pygame.image.load('dragon_1.gif'), pygame.image.load('dragon_2.gif'), pygame.image.load('dragon_3.gif'), pygame.image.load('dragon_4.gif'), pygame.image.load('dragon_5.gif'), pygame.image.load('dragon_6.gif')]
for i in range (6):
walkleft[i] = pygame.transform.scale(walkleft[i],(200,176))
def __init__(self,enemy_x,enemy_y, end):
self.x = enemy_x
self.y = enemy_y
self.end = end
self.path = [self.x,self.end]
self.walkcount = 0
self.vel = 7
self.hitbox = (self.x,self.y-15,90,90)
def draw_enemy(self,window):
self.move()
if self.walkcount >= 6:
self.walkcount = 0
#walking left
if self.vel > 0:
window.blit(self.walkleft[self.walkcount], (self.x,300))
self.walkcount += 1
self.vel+=0.002
if self.x < -120:
self.x = 1100
self.hitbox = (self.x+25,self.y-15,41,70)
pygame.draw.rect(window, (255,0,0),self.hitbox,2)
def move(self):
if self.vel > 0:
#see if position + movement space is < the end, then it is able to move
if self.x + self.vel < self.path[1]:
self.x -= self.vel
#past end point and turns 180
else:
self.vel = self.vel*-1
self.walkcount = 0
#see if position is smaller than starting position
else:
if self.x - self.vel > self.path[0]:
#vel is already negative
self.x += self.vel
else:
#Truns 180 agian
self.vel = self.vel* -1
self.walkcount = 0
ghost_list = []
eye_list = []
def keepdrawing():
window.blit(background, (background_x,0))
window.blit(background, (background_2,0))
for draw_ghost in ghost_list:
draw_ghost.draw(window)
for draw_eye in eye_list:
draw_eye.draw(window)
adventurer.movement(window)
attacker.draw_enemy(window)
wizard.draw_enemy(window)
dragon.draw_enemy(window)
score_text = score_font.render("score: " + str(score), 1, (0,0,0))
window.blit(score_text,(470,10))
pygame.display.update()
score_font = pygame.font.SysFont("Arial",30,True)
attacker = enemy(950,407,951)
adventurer = player(40,387)
wizard = wizard(905,407,951)
dragon = dragon(905,407, 951)
vel_background = 2
pygame.time.set_timer(pygame.USEREVENT+1,random.randint(1000, 2000))
pygame.time.set_timer(pygame.USEREVENT+2,random.randint(2000, 3000))
while run:
while run_program:
clock.tick(60)
background_x -= vel_background
background_2 -= vel_background
if background_x < background.get_width() * -1:
background_x = background.get_width()
if background_2 < background.get_width() * -1:
background_2 = background.get_width()
keys = pygame.key.get_pressed()
if (adventurer.hitbox_running[0] > attacker.hitbox[0] and adventurer.hitbox_running[0] < attacker.hitbox[0]+70) or (adventurer.hitbox_running[0]+70 > attacker.hitbox[0] and adventurer.hitbox_running[0]+90 < attacker.hitbox[0]+70):
if (adventurer.hitbox_running[1] > attacker.hitbox[1] and adventurer.hitbox_running[1] < attacker.hitbox[1]+70) or (adventurer.hitbox_running[1]+90 > attacker.hitbox[1] and adventurer.hitbox_running[1]+90 < attacker.hitbox[1]+70):
window.fill((255,255,255))
death()
pygame.display.update()
s(0.1)
print("hit")
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
exit()
if event.type == pygame.USEREVENT+1:
vel_background+=0.2
if event.type == pygame.USEREVENT+2:
r = random.randint(0,1)
if r==0:
new_eye = eye(1050, 390, 64,64)
eye_list.append(new_eye)
if r==1:
new_ghost = ghost(1050,390,64)
ghost_list.append(new_ghost)
if not(adventurer.isJump):
if keys[pygame.K_UP]:
adventurer.isJump =True
else:
if adventurer.jumpcount >= -10:
neg=1
if adventurer.player_y > adventurer.width:
adventurer.player_y = adventurer.width
if adventurer.jumpcount <0:
neg = -1
## s(0.01)
adventurer.player_y -= (adventurer.jumpcount**2)*adventurer.fallspeed*neg*2
## s(0.01)
adventurer.jumpcount -=1
if adventurer.player_y > adventurer.width:
adventurer.player_y=adventurer.width
else:
adventurer.isJump = False
adventurer.jumpcount = 10
if adventurer.player_y > adventurer.width:
player_y = adventurer.width
adventurer.fallspeed = 0.05
keepdrawing()
The expected results should be that the output should not be shit if the hit boxes are not in contact.
The major issue is that you've different "hitboxis, which have different meanings at different states of the game, but you use adventurer.hitbox_running for the collison test event if adventurer is .running or .falling.
The best solution would be the set one .hitbox attribute, which always contains the proper location of adventurer in the method player.movement.
But it is also possible the choose the proper hit box:
if adventurer.running:
hitbox = adventurer.hitbox_running
elif adventurer.jumping:
hitbox = adventurer.hitbox_jumping
elif adventurer.falling:
hitbox = adventurer.hitbox_falling
Further I recommend to use pygame.Rect objects and .colliderect() for the collision test:
rect_adventurer = pygame.Rect(*hitbox)
rect_attacker = pygame.Rect(*attacker.hitbox)
if rect_adventurer.colliderect(rect_attacker):
window.fill((255,255,255))
death()
pygame.display.update()
s(0.1)
print("hit")