How do I use Images in pygame for collision detection [duplicate] - python

This question already has answers here:
How to detect collisions between two rectangular objects or images in pygame
(1 answer)
Why is my collision test always returning 'true' and why is the position of the rectangle of the image always wrong (0, 0)?
(1 answer)
How do I detect collision in pygame?
(5 answers)
Closed 2 years ago.
import pygame
import os
pygame.init()
# Images
bgImg = pygame.image.load("Images/background.png")
playerImgRight = (pygame.image.load("Images/playerRight.png"))
playerImgLeft = pygame.image.load("Images/playerLeft.png")
playerImgBack = pygame.image.load("Images/playerBack.png")
chestClosed = pygame.transform.scale(pygame.image.load("Images/chestsClosed.png"), (30, 40))
chestOpened = pygame.transform.scale(pygame.image.load("Images/chestOpen.png"), (30, 40))
currentPlayerImg = playerImgBack
screen = pygame.display.set_mode((800, 800))
pygame.display.set_caption("Richmonia")
pygame.display.set_icon(currentPlayerImg)
clock = pygame.time.Clock()
playerX = 380
playerY = 380
playerXSpeed = 0
playerYSpeed = 0
Chest Class
I want but the collision detection in the chest update function
class Chest:
def __init__(self, x, y, openImage, closeImage, playerX, playerY):
self.x = x
self.y = y
self.openImage = openImage
self.closeImage = closeImage
self.currentImage = self.closeImage
self.playerX = playerX
self.playerY = playerY
def update(self):
print("Placeholder")
def show(self):
screen.blit(self.currentImage, (self.x, self.y))
chestOne = Chest(100, 100, chestOpened, chestClosed, playerX, playerY)
running = True
while running:
clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_UP:
currentPlayerImg = playerImgBack
playerYSpeed = -5
if event.key == pygame.K_DOWN:
currentPlayerImg = playerImgBack
playerYSpeed = 5
if event.key == pygame.K_LEFT:
currentPlayerImg = playerImgLeft
playerXSpeed = -5
if event.key == pygame.K_RIGHT:
currentPlayerImg = playerImgRight
playerXSpeed = 5
if event.type == pygame.KEYUP:
if event.key == pygame.K_UP:
playerYSpeed = 0
if event.key == pygame.K_DOWN:
playerYSpeed = 0
if event.key == pygame.K_LEFT:
playerXSpeed = 0
if event.key == pygame.K_RIGHT:
playerXSpeed = 0
if playerY <= 0:
playerY = 0
if playerY >= 740:
playerY = 740
if playerX <= 0:
playerX = 0
if playerX >= 760:
playerX = 760
playerX += playerXSpeed
playerY += playerYSpeed
screen.blit(bgImg, (0, 0))
chestOne.show()
chestOne.update()
screen.blit(currentPlayerImg, (playerX, playerY))
pygame.display.update()
pygame.quit()
quit()
I know there is a way with sprites but I want to know if there is a way to do it with just the images.
Also bonus question how to I get the fps.

Use a pygame.Rect object and colliderect() to find a collision between a rectangle and an object.
pygame.Surface.get_rect.get_rect() returns a rectangle with the size of the Surface object, that always starts at (0, 0) since a Surface object has no position. The position of the rectangle can be specified by a keyword argument:
running = True
while running:
# [...]
player_rect = currentPlayerImg.get_rect(topleft = (playerX, playerY))
chestOne_rect = chestOne.currentImage.get_rect(topleft = (self.x, self.y))
if player_rect .colliderect(chestOne_rect):
print("hit")
# [...]
The method tick() of a pygame.time.Clock object, delays the game in that way, that every iteration of the loop consumes the same period of time.
So in your case the frames per second are 60:
while running:
clock.tick(60)
pygame.time.Clock.tick returns the number of milliseconds passed since the previous call. If you call it in the application loop, then this is the number of milliseconds passed since the last frame.
while run:
ms_since_last_frame = clock.tick(60)

Related

How to make accurate collisions in pygame? [duplicate]

This question already has answers here:
How do I detect collision in pygame?
(5 answers)
Closed 20 days ago.
I am making a platformer and am trying to make a player be able to stay on top of a platform. When I check if they are colliding, I check if the bottom of the player meets the top of the platform. It doesn't give an output, can someone please help?
The buggy part is the collisions where playerRect.colliderect(platform): and the bit below that as well. Help would be much appreciated.
import pygame
pygame.init()
screen = pygame.display.set_mode((1400, 900))
clock = pygame.time.Clock()
playerX = 700
playerY = 870
jumping = False
goingRight = False
goingLeft = False
jumpSpeed = 1
jumpHeight = 18
yVelocity = jumpHeight
gravity = 1
speed = 6
white = (255, 255, 255)
black = (0, 0, 0)
running = True
while running:
screen.fill(black)
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
keys = pygame.key.get_pressed()
if keys[pygame.K_SPACE]:
jumping = True
if keys[pygame.K_LEFT]:
goingLeft = True
if keys[pygame.K_RIGHT]:
goingRight = True
platform = pygame.draw.rect(screen, white, (100, 840, 100, 30))
playerRect = pygame.draw.rect(screen, white, (playerX, playerY, 30, 30))
if jumping:
playerY -= yVelocity
yVelocity -= gravity
if yVelocity < -jumpHeight:
jumping = False
yVelocity = jumpHeight
if goingLeft:
playerX -= speed
if goingRight:
playerX += speed
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT:
goingLeft = False
if event.key == pygame.K_RIGHT:
goingRight = False
if playerRect.colliderect(platform):
if playerRect.bottom - platform.top == 0:
playerRect.bottom = platform.y
pygame.display.update()
clock.tick(60)
`
Most likely this part is the problem.
if playerRect.bottom - platform.top == 0:
You should check if bottom of the player is higher than the top of the platform since chance of them being exact is not high since your yVelocity is different than 1.

How to use time and make a timer in Pygame? [duplicate]

This question already has answers here:
Countdown timer in Pygame
(8 answers)
Spawning multiple instances of the same object concurrently in python
(1 answer)
Closed 5 months ago.
I am new to pygame programming and I am making a game with the help of tutorials. I finished the tutorial and want to add a new feature to my game.
Game Overview
I have created a space invader game where there are enemies moving on the x-axis and slowly coming down. In bottom there is a space ship which can move on the x axis and can shoot bullets to destroy or kill the enemies. The enemies respawn after being killed and if an enemy reaches the bottom, it is game over
Code
# importing modules
import pygame
import random
import math
from pygame import mixer
# initialize pygame
pygame.init()
# creating a window
screen = pygame.display.set_mode((800, 600))
# Background Music
mixer.music.load('background.wav')
mixer.music.play(-1)
# Background
bg_img = pygame.image.load("background3.png")
bg = pygame.transform.scale(bg_img, (800, 600))
# Title and Icon
pygame.display.set_caption("Space Shooters")
icon = pygame.image.load('spaceship.png')
pygame.display.set_icon(icon)
# Player
player = pygame.image.load('spaceship2.png')
playerX = 370
playerY = 500
playerX_change = 0
# Enemy
enemyImg = []
enemyX = []
enemyY = []
enemyX_change = []
enemyY_change = []
num_of_enemies = 6
for i in range(num_of_enemies):
enemyImg.append(pygame.image.load('enemy.png'))
enemyX.append(random.randint(6, 730))
enemyY.append(random.randint(45, 150))
enemyX_change.append(0.3)
enemyY_change.append(40)
# Bullet
# Ready - The bullet can't be seen
# Fire - The bullet has been shot
bulletImg = pygame.image.load('bullet.png')
bulletX = 0
bulletY = 480
bulletX_change = 0
bulletY_change = 1.5
bullet_state = "Ready"
# Score
score_value = 0
font = pygame.font.Font('freesansbold.ttf', 32)
textX = 10
textY = 10
# Game Over
over_font = pygame.font.Font('freesansbold.ttf', 64)
# Function for displaying text
def show_score(x, y):
score = font.render("Score : " + str(score_value), True, (255, 255, 255))
screen.blit(score, (x, y))
def game_over_text():
over_text = over_font.render("GAME OVER", True, (255, 255, 255))
screen.blit(over_text, (200, 250))
# Defining and drawing spaceship
def spaceship(x, y):
screen.blit(player, (x, y))
# Defining and drawing enemy
def enemy(x, y, i):
screen.blit(enemyImg[i], (x, y))
def fire_bullet(x, y):
global bullet_state
bullet_state = "Fire"
screen.blit(bulletImg, (x + 16, y + 10))
def Iscollision(enemyX, enemyY, bulletX, bulletY):
distance = math.sqrt((math.pow(enemyX - bulletX, 2)) + (math.pow(enemyY - bulletY, 2)))
if distance < 27:
return True
else:
return False
# making the game window run endlessly and game loop
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
# Keystroke check (right, left)
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
playerX_change = -0.3
if event.key == pygame.K_RIGHT:
playerX_change = 0.3
if event.key == pygame.K_SPACE:
# Checking whether bullet is there on screen, if not making it ready, if yes disabling spacebar
if bullet_state == "Ready":
# Get the current X cordinate of spaceship
bulletX = playerX
fire_bullet(bulletX, bulletY)
bullet_sound = mixer.Sound('laser.wav')
bullet_sound.play()
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
playerX_change = 0
# Changing X coordinates to move spaceship
playerX += playerX_change
if playerX <= 6:
playerX = 6
elif playerX >= 730:
playerX = 730
screen.fill(0)
screen.blit(bg, (0, 0))
# Enemy Movement
for i in range(num_of_enemies):
# Game Over
if enemyY[i] > 440:
for j in range(num_of_enemies):
enemyY[j] = 2000
game_over_text()
break
for i in range(num_of_enemies):
enemyX[i] += enemyX_change[i]
if enemyX[i] <= 6:
enemyX_change[i] = 0.3
enemyY[i] += enemyY_change[i]
elif enemyX[i] >= 730:
enemyX_change[i] = -0.3
enemyY[i] += enemyY_change[i]
# Collision
collision = Iscollision(enemyX[i], enemyY[i], bulletX, bulletY)
# if collision and if collision is true are both the same
if collision:
collision_sound = mixer.Sound('explosion.wav')
collision_sound.play()
bulletY = 480
bullet_state = "Ready"
score_value += 1
enemyX[i] = random.randint(6, 730)
enemyY[i] = random.randint(45, 150)
enemy(enemyX[i], enemyY[i], i)
# Deleting each frame of enemy moving so that it runs smoothly
# Bullet Movement
if bulletY <= 0:
bulletY = 480
bullet_state = "Ready"
if bullet_state == "Fire":
fire_bullet(bulletX, bulletY)
bulletY -= bulletY_change
spaceship(playerX, playerY)
show_score(textX, textY)
# updating display
pygame.display.update()
New Feature
I want to add a feature that when a laser ( I have a picture) hits the spaceship, shot by the enemies, the spaceship can't move for 10 seconds. I have already tryed other stack overflow questions but they don't match my needs.
If you only have one cooldown to manage, a simple and clean way to do it is by using a custom event :
# Custom event
COOLDOWN_END = pg.USEREVENT
When you detect a collision you simply start a timer :
# Custom event
pg.time.set_timer(COOLDOWN_END, 1000, 1)
The first parameter is the event you are going to send to your event handler, the 2nd is the time in ms (so 1 sec here) and last one is the number of iteration. Here you just want to send the event once, so put 1.
The last step is to do catch this event in your handler and do what you want with it :
for evt in pg.event.get():
if evt.type == pg.QUIT:
exit()
if evt.type == COOLDOWN_END:
print(evt)
# Your logic goes here
Let's put everything together :
(Here, I simply used this technique to have a COOLDOWN_END event 1 sec after I clicked)
# General imports
import pygame as pg
import sys
# Init
pg.init()
# Vars
screen = pg.display.set_mode((500, 500))
pg.display.set_caption("name")
# Clock
FPS = 60
clock = pg.time.Clock()
# Custom event
COOLDOWN_END = pg.USEREVENT
# Main functions
def update():
pass
def draw():
# Clear screen
screen.fill((0,0,0))
def handle_evt():
for evt in pg.event.get():
if evt.type == pg.QUIT:
exit()
if evt.type == pg.KEYDOWN:
if evt.key == pg.K_ESCAPE:
exit()
if evt.type == pg.MOUSEBUTTONDOWN:
if evt.button == 1:
on_click()
if evt.type == COOLDOWN_END:
print(evt)
def on_click():
pg.time.set_timer(COOLDOWN_END, 1000, 1)
def exit():
pg.quit()
sys.exit()
# Main loop
if __name__ == '__main__':
while True:
handle_evt()
update()
draw()
clock.tick(FPS)
pg.display.flip()
You may use custom event with from pygame.locals import USEREVENT.
An alternative is to keep track of time of when you got hit using pygame.time.get_ticks() + some stun cooldown system, and applying only to the portion of the code involved with player movement.
stun_duration = 10000 # milliseconds
damaged_timestamp = -stun_duration # allows to get stunned starting from pygame.init() call
running = True
while running:
for event in pygame.event.get():
# preceding code
# check if beyond stun cooldown
if pygame.time.get_ticks() - damaged_timestamp > stun_duration:
damaged_timestamp = pygame.time.get_ticks()
# Keystroke check (right, left)
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
playerX_change = -0.3
if event.key == pygame.K_RIGHT:
playerX_change = 0.3
if event.key == pygame.K_SPACE:
# Checking whether bullet is there on screen, if not making it ready, if yes disabling spacebar
if bullet_state == "Ready":
# Get the current X cordinate of spaceship
bulletX = playerX
fire_bullet(bulletX, bulletY)
bullet_sound = mixer.Sound('laser.wav')
bullet_sound.play()
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
playerX_change = 0
# Changing X coordinates to move spaceship
playerX += playerX_change
if playerX <= 6:
playerX = 6
elif playerX >= 730:
playerX = 730
# proceeding code

Why does "Game over" text not appear?

I am currently attempting to programm a small game. An enemy is supposed to chase the player, the actual chasing is not implemented yet. I still need to figure out how to do that, but that's not the question.
I have made it so that the player returns to the start point once they collide with the enemy. In addition to that, a text 'Game over' is supposed to appear. The function for that is called at the end of the game loop and while the text appeared briefly(it actually only appeared once, I have tried it multiple times), it does not stay. I was planing on making it appear and then disappear after a few seconds so that the player can play again, but I'm not sure why it disappears instantly.
If this is the wrong place to post this, please tell me, I will delete this post. This is my code, would be amazing if somebody could help me out:
import pygame #imports pygame
import math
pygame.init()
#screen
screen = pygame.display.set_mode((800,600)) #width and height
#title and icon
pygame.display.set_caption("The Great Chase") #changes title
icon = pygame.image.load('game-controller.png')
pygame.display.set_icon(icon) #setting icon
#player
playerImg = pygame.image.load('scary-monster.png')
playerX = 370
playerY = 480
playerX_change = 0
playerY_change = 0
#enemy
enemyImg = pygame.image.load('caterpillar.png')
enemyX = 370
enemyY = 50
enemyX_change = 0
enemyY_change = 0
#GAME OVER
game_over_font = pygame.font.Font('Bubblegum.ttf',64)
def game_over_text():
game_over_text = game_over_font.render("GAME OVER", True, (255, 0, 0))
screen.blit(game_over_text, (200, 250))
def player(x, y): #function for player
screen.blit(playerImg, (x, y)) #draws image of player, blit -> means to draw
def enemy(x, y): #function for enemy
screen.blit(enemyImg,(x,y))
def isCollision(playerX, playerY, enemyX, enemyY):
distance = math.sqrt((math.pow(playerX-enemyX,2)) + (math.pow(playerY - enemyY,2)))
if distance < 25:
return True
else:
return False
def chase():
distance = math.sqrt((math.pow(playerX-enemyX,2)) + (math.pow(playerY - enemyY,2)))
#Game loop
running = True
while running:
screen.fill((255,255,0)) #0-255 RGB-> red, green & blue
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
# if keystroke check whether right or left or up or down
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
playerX_change = -0.2
if event.key == pygame.K_RIGHT:
playerX_change = 0.2
if event.key == pygame.K_UP:
playerY_change = -0.2
if event.key == pygame.K_DOWN:
playerY_change = 0.2
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
playerX_change = 0
if event.key == pygame.K_UP or event.key == pygame.K_DOWN:
playerY_change = 0
playerX += playerX_change
playerY += playerY_change
#creating borders so that player won't leave screen
if playerX <=0:
playerX = 0
elif playerX >=768:
playerX = 768
if playerY <= 0:
playerY = 0
elif playerY >=568:
playerY = 568
#collision
collision = isCollision(playerX, playerY, enemyX, enemyY)
if collision:
playerY = 480
game_over_text()
player(playerX, playerY)
enemy(enemyX, enemyY)
pygame.display.update()
The collision only occurs for a moment and the game over text is only shown when the object collides. If you want to persist the text, set a gameover variable when the collision is detected and display the text based on the state of the variable:
gameover = False
running = True
while running:
# [...]
collision = isCollision(playerX, playerY, enemyX, enemyY)
if collision:
playerY = 480
gameover = True
player(playerX, playerY)
enemy(enemyX, enemyY)
if gameover:
game_over_text()
pygame.display.update()
Note, collision is set in every frame depending on the position of the objects. However, gameover is set once when a collision occurs and then maintains its state.

How do i detect if my character collided with an enemy and closes the game if it hits 3 times [duplicate]

This question already has answers here:
How to detect collisions between two rectangular objects or images in pygame
(1 answer)
Why is my collision test always returning 'true' and why is the position of the rectangle of the image always wrong (0, 0)?
(1 answer)
How do I detect collision in pygame?
(5 answers)
Closed 2 years ago.
I want to make it kind of like a life system so that if it collides with the enemy 3 times it will quit
pygame.init()
screen_width = 800
screen_height = 600
window = pygame.display.set_mode((screen_width, screen_height))
pygame.display.set_caption('Test')
time = pygame.time.Clock()
bg_color1 = (135, 142, 142) # MAIN BG COLOR
bg_color2 = (255, 0, 0) # red
bg_color3 = (255, 255, 0) # yellow
UFO = pygame.image.load('ufo.png')
bg_pic = pygame.image.load('Letsgo.jpg')
clock = pygame.time.Clock()
playerImg = pygame.image.load('enemy.png')
playerX = random.randrange(0, screen_width)
playerY = -50
playerX_change = 0
player_speed = 5
def player(x, y):
window.blit(playerImg, (playerX, playerY))
crashed = False
rect = UFO.get_rect()
obstacle = pygame.Rect(400, 200, 80, 80)
menu = True
playerY = playerY + player_speed
if playerY > screen_height:
playerX = random.randrange(0, screen_width)
playerY = -25
def ufo(x, y):
window.blit(UFO, (x, y))
while menu:
for event in pygame.event.get():
if event.type == pygame.QUIT:
quit()
elif event.type == pygame.MOUSEBUTTONDOWN:
if event.button == 1:
menu = False
window.fill((0, 0, 0))
time.tick(30)
window.blit(bg_pic, (0, 0))
pygame.display.update()
x = (screen_width * 0.45)
y = (screen_height * 0.8)
x_change = 0
car_speed = 0
y_change = 0
while not crashed:
x += x_change
if x < 0:
x = 0
elif x > screen_width - UFO.get_width():
x = screen_width - UFO.get_width()
y += y_change
if y < 0:
y = 0
elif y > screen_height - UFO.get_height():
y = screen_height - UFO.get_height()
for event in pygame.event.get():
if event.type == pygame.QUIT:
crashed = True
############SIDE TO SIDE################
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
x_change = -5
elif event.key == pygame.K_RIGHT:
x_change = 5
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
x_change = 0
###########UP AND DOWN#################
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_UP:
y_change = -5
elif event.key == pygame.K_DOWN:
y_change = 5
if event.type == pygame.KEYUP:
if event.key == pygame.K_UP or event.key == pygame.K_DOWN:
y_change = 0
if playerY > screen_height:
playerX = random.randrange(0, screen_width)
playerY = 0
playerY += 10
##
window.fill(bg_color1)
ufo(x, y)
player(playerX, playerY)
pygame.display.update()
clock.tick(100)
pygame.quit()
quit()
im thinking of using a collide.rect but cant figure it out any help is appreciated
I want the "playerImg" to be the enemy ...................................................................................
Create a variable that stores the number of lives. Create pygme.Rect objects of the player and the UFO with the method get_rect. Set the location of the rectangles by keyword arguments. Use colliderect to test the collision and decrease the number of lives when a collision is detected and create a new random starting position:
lives = 3
while not crashed:
# [...]
player_rect = playerImg.get_rect(topleft = (playerX, playerY))
ufo_rect = UFO.get_rect(topleft = (x, y))
if player_rect.colliderect(ufo_rect):
lives -= 1
print(lives)
playerX = random.randrange(0, screen_width)
playerY = 0
if lives == 0:
crashed = True
# [...]

Pygame The collision for my game works, but only for the last placed image

import pygame, random, time
class Game(object):
def main(self, screen):
bg = pygame.image.load('data/bg.png')
house1 = pygame.image.load('data/house1.png')
playerIdle = pygame.image.load('data/playerIdle.png')
playerRight = pygame.image.load('data/playerRight.png')
playerLeft = pygame.image.load('data/playerLeft.png')
playerUp = pygame.image.load('data/playerUp.png')
playerX = 0
playerY = 50
clock = pygame.time.Clock()
spriteList = []
gameIsRunning = False
house1Selected = False
houseInWorld = False
while 1:
clock.tick(30)
mouse = pygame.mouse.get_pos()
for event in pygame.event.get():
if event.type == pygame.QUIT:
return
if event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE:
return
#delete all sprites on the game(only able to do this in god mode)
if event.type == pygame.KEYDOWN and event.key == pygame.K_d and gameIsRunning == False:
spriteList = []
#press 6 to select the house1 image to be placed
if event.type == pygame.KEYDOWN and event.key == pygame.K_6 and gameIsRunning == False:
house1Selected = True
#spawning the image"house1" at the position of the mouse by pressing space
if event.type == pygame.KEYDOWN and event.key == pygame.K_SPACE and gameIsRunning == False and house1Selected == True:
spriteList.append((house1, mouse))
house1XY = mouse
houseInWorld = True
#run mode where you cannot build and you move(where I want collision)
if event.type == pygame.KEYDOWN and event.key == pygame.K_r:
gameIsRunning = True
#god mode where you can build and place the house1 image
if event.type == pygame.KEYDOWN and event.key == pygame.K_g:
gameIsRunning = False
#this is run mode where you can move around and where I want collision
if(gameIsRunning == True):
#player Movements
if event.type == pygame.KEYDOWN and event.key == pygame.K_UP:
if playerY <= 0:
playerY = 0
if playerY >= 0:
screen.blit(playerUp, (playerX, playerY))
playerY = playerY - 2
if event.type == pygame.KEYDOWN and event.key == pygame.K_DOWN:
PLAYERDOWNLIMIT = 700 - playerIdle.get_height()
if(playerY >= PLAYERDOWNLIMIT):
playerY = PLAYERDOWNLIMIT
if(playerY <= PLAYERDOWNLIMIT):
screen.blit(playerIdle, (playerX, playerY))
playerY = playerY + 2
if event.type == pygame.KEYDOWN and event.key == pygame.K_LEFT:
if playerX <= 0:
playerX = 0
if playerX >= 0:
screen.blit(playerLeft, (playerX, playerY))
playerX = playerX - 2
if event.type == pygame.KEYDOWN and event.key == pygame.K_RIGHT:
PLAYERRIGHTLIMIT = 1200 - playerIdle.get_width()
if(playerX >= PLAYERRIGHTLIMIT):
playerX = PLAYERRIGHTLIMIT
if(playerX <= PLAYERRIGHTLIMIT):
screen.blit(playerRight, (playerX, playerY))
playerX = playerX + 2
#collision
if(house1InWorld == True):
house1Rect = pygame.Rect(house1XY[0], house1XY[1], 64, 64)
if playerRect.colliderect(house1Rect) and playerX <= house1XY[0]:
playerX = playerX - 2
if playerRect.colliderect(house1Rect) and playerX >= house1XY[0]:
playerX = playerX + 2
if playerRect.colliderect(house1Rect) and playerY <= house1XY[1]:
playerY = playerY - 2
if playerRect.colliderect(house1Rect) and playerY >= house1XY[1]:
playerY = playerY + 2
#this is godmode where you can move around fast n preview where you place images but I don't want collision here
if(gameIsRunning == False):
if event.type == pygame.KEYDOWN and event.key == pygame.K_UP:
if playerY <= 0:
playerY = 0
if playerY >= 0:
screen.blit(playerUp, (playerX, playerY))
playerY = playerY - 8
if event.type == pygame.KEYDOWN and event.key == pygame.K_DOWN:
PLAYERDOWNLIMIT = 700 - playerIdle.get_height()
if(playerY >= PLAYERDOWNLIMIT):
playerY = PLAYERDOWNLIMIT
if(playerY <= PLAYERDOWNLIMIT):
screen.blit(playerIdle, (playerX, playerY))
playerY = playerY + 8
if event.type == pygame.KEYDOWN and event.key == pygame.K_LEFT:
if playerX <= 0:
playerX = 0
if playerX >= 0:
screen.blit(playerLeft, (playerX, playerY))
playerX = playerX - 8
if event.type == pygame.KEYDOWN and event.key == pygame.K_RIGHT:
PLAYERRIGHTLIMIT = 1200 - playerIdle.get_width()
if(playerX >= PLAYERRIGHTLIMIT):
playerX = PLAYERRIGHTLIMIT
if(playerX <= PLAYERRIGHTLIMIT):
screen.blit(playerRight, (playerX, playerY))
playerX = playerX + 8
screen.fill((200, 200, 200))
screen.blit(bg, (0, 0))
#what block are you placing(displays preview)
if(gameIsRunning == False and house1Selected == True):
screen.blit(house1, (mouse))
if(gameIsRunning == True):
playerXSTR = str(playerX)
playerYSTR = str(playerY)
playerXYSTR = ("(" + playerXSTR + ", " + playerYSTR + ")")
font = pygame.font.SysFont("monospace", 15)
playercord = font.render(playerXYSTR, 1, (255,255,255))
screen.blit(playercord, (0, 0))
runMode = font.render("Run Mode(Cannot build)", 1, (255,255,255))
screen.blit(runMode, (0, 20))
if(gameIsRunning == False):
playerXSTR = str(playerX)
playerYSTR = str(playerY)
playerXYSTR = ("(" + playerXSTR + ", " + playerYSTR + ")")
font = pygame.font.SysFont("monospace", 15)
playercord = font.render(playerXYSTR, 1, (255,255,255))
screen.blit(playercord, (0, 0))
godMode = font.render("God Mode(Can build)", 1, (255,255,255))
screen.blit(godMode, (0, 20))
for (img, pos) in spriteList:
screen.blit(img, pos)
screen.blit(playerIdle, (playerX, playerY))
pygame.display.flip()
if __name__ == '__main__':
pygame.init()
screen = pygame.display.set_mode((1200, 700))
pygame.display.set_caption('Sandbox')
Game().main(screen)
In my game, you start in "god mode", where you can place objects. When you finish placing objects and go into "run mode", however, the game is in realtime and there's collision and other physical effects.
So the collision I have in my game right now works only part of the time.
When you press space, you spawn the 'house1' image at the location of the mouse and it sets the house1's XY coordinates, and sets house1InWorld = True (which affects collision).
Collision is goes into effect when the house1 image is spawned, because of the house1inWorld attribute. So if you press r (to go into run mode), the collision works for one house1 instance. But when you spawn 2 instances of house1 (at different locations), the collision only works for the recently placed house1.
How should I change my code so that collision works no matter how many house1's you spawn?
You only store the position of the last placed house and check the collision against that.
You should create a list of house positions, and loop though them to check for collision.
Something like this:
houses1XY = []
houses1XY.append(mouse)
#and later
for house1XY in houses1XY:
house1Rect = pygame.Rect(house1XY[0], house1XY[1], 64, 64)
Since you moved the houses to a list, you no longer need the houseInWorld. You already have the information about in the list. You can check if the list is not empty -> so there is a house placed already by evaluating the list. It returns true if it is not empty.
if houses1XY:
#enable realtime etc.

Categories

Resources