Bouncing Ball doesn't come back pygame - python

import pygame
pygame.init()
width = 400
hight = 600
screen = pygame.display.set_mode((width, hight))
pygame.display.set_caption("Engine")
dot = pygame.image.load("KreisSchwarz.png")
clock = pygame.time.Clock()
running = True
WHITE = (255, 255, 255)
# Set (x, y) for Dot
def updateDot(x, y):
screen.blit(dot, (x, y))
# Display Dot at (x, y)
def update(fps=30):
screen.fill(WHITE)
updateDot(x, y)
pygame.display.flip()
return clock.tick(fps)
# Quit if User closes the window
def evHandler():
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
running = False
yKoords = []
(x, y) = (300, 200)
t = 1 # time variable
a = 2 # acceleration constant
tol = 40 # tolerance
i = 0 # just some iterator
# MAIN LOOP
while running:
evHandler()
update()
y += a * (t ^ 2)
t += 1
yKoords.append(int(y))
i += 1
if (y < (hight + tol)) and (y > (hight - tol)):
y = 580
yKoords.reverse()
update()
for q in range(i):
evHandler()
y = yKoords[q]
update()
if q == i - 1: # Because i didn't write the Part for the Dot coming back down
running = False
This is my Code for a Ball accelerating down and then jumping back up.
My Problem is, that the code works fine until the if statement. There the Programm just displays the Ball at the last position in yKoords and waits until the for loop finishes. If i remove the for loop the Ball gets displayed at y=580 and stops but thats fine.
Please help i have no idea whats wrong about this.

Don't do a separate process loop in the main loop.
It is sufficient to invert the direction, when the ball bounce on the ground (abs(y - hight)) or the ball reaches the top (t == 0).
direction = 1
while running:
evHandler()
update()
y += (a * (t ^ 2)) * direction
t += direction
if abs(y - hight) < tol:
y = 580
t -= 1
direction *= -1
elif t == 0:
direction *= -1

Related

Pygame not letting me change display after .update()

I've put pygame.display.update() multiple different places but for some reason it absolutely doesnt let me do the H keypress so it draws help, everything else works.
This is for a school assignment that ive made much harder than it was. I'm technically done i just wanted to make a main menu, everything went smooth then the help screen never wanted to draw
import pygame
import time
import random
import sys
import os
# ! Use print(event) for coordinate reading
# TODO: Add highscore file read and overwrite ✔️
# TODO: Add Game over message ✔️
# TODO: Show highscore and points of that run ✔️
# TODO: Fix Snake not being on same x,y as apple (Most likely wrong movement increments) ✔️
# TODO: Add GRID ✔️
# ? Find a better spawning logic ✔️
# ? Add menu instead of a simple string - NOE AV DET JÆVLIGSTE JEG HAR STARTET PÅ
# ? Fine tune resolution and size
# ? Add a unique powerup with 3% spawn chance giving 5 points and 1 body length
# ! Pygame Initiatior
pygame.init() # * Initiates pygame
# ! Screen resolution and title
sc_width = 400
sc_height = 400
screen = pygame.display.set_mode((sc_width, sc_height)) # * Sets pygame window
pygame.display.set_caption('Snake') # * Sets window title to Snake
# ! Color Variables
bgcolor = (25, 51, 102) # * Dark blue for background color
yellow = (255, 255, 0) # * Yellow color for snake
red = (255, 0, 0) # * Red color for points & game over
white = (255, 255, 255) # * White color for score
# ! FPS variable
clock = pygame.time.Clock() # * Used to set the FPS of the game using clock.tick(xyz)
# ! Font
font = pygame.font.SysFont(None, 30) # * None = Default pygame font. 40 = size of font
# ! Game Over Draw function
def GameOver(msg, color): # * Function takes in a string and color and draws it on screen
text = font.render(msg, True, color) # * Draws msg with font with True for anti aliasing (Smooth edges) with specified color when func is called
screen.blit(text, [50, 100]) # * Draws text at 100x100
# ! Snake
snake_block = 10
def Snake(snake_block, snakelist):
for x in snakelist:
pygame.draw.rect(screen, yellow, [x[0], x[1], snake_block, snake_block])
# ! Grid
black = (0, 0, 0)
def Grid():
size = 10 # * Sets grid size to 10 (same as snake)
for x2 in range(0, sc_width, size): # * Gaps 10 in width
for y2 in range(0, sc_height, size): # * Gaps height with 10
drawGrid = pygame.Rect(x2, y2, size, size) # * Makes a grid
pygame.draw.rect(screen, black, drawGrid, 1) # * Draws it onto the screen
# ! Draw Score
def drawScore(score):
points = font.render('Score: ' + str(score), True, white)
screen.blit(points, [0, 0]) # * Draws it top left
# ! Make highscore txt
try:
f = open("highscore.txt", 'x') # * Creates file if it doesnt exist
f.write('0') # * No highscore set
f.close() # * Closes file to let other codes down the line rewrite the file
except FileExistsError: # * If exist continue to rest of code using it as the "highscore" file
pass
# ! Draw Highscore
f = open('highscore.txt', 'r') # * Opens as read
highscore = int(f.readline())
f.close()
def drawHighscore(highscore):
hc = font.render('Score: ' + str(highscore), True, white)
screen.blit(hc, [310, 0]) # * Draws it top right
# # ! Draw PRE GAME Screen
# def drawMenu(menu, color):
# pregame = font.render(menu, True, white)
# screen.blit(pregame, [50, 100])
# ! Multiline draw function (Stackoverflow) / PRE GAME
def drawMenu(menu, x, y, fsize):
lines = menu.splitlines()
for i, l in enumerate(lines):
screen.blit(font.render(l, 0, white), (x, y + fsize*i))
# ! Draw Help screen
def drawHelp(x, y, fsize):
help = "Controls: [W][A][S][D]\nInstructions: \nUse WASD to control the snake.\nGrab as many apples as you can;\nand dont crash into yourself :)\n\n [ (B) A C K ]"
hlp = help.splitlines()
for i, l in enumerate(hlp):
screen.blit(font.render(l, 0, white), (x, y + fsize*i))
def mainMenu():
menu = "[ (S) T A R T ]\n [ (H) E L P ]\n [ (Q) U I T ]\n jeg er best"
screen.fill(bgcolor)
drawMenu(menu, 140, 120, 80)
for event in pygame.event.get(): # * Gathers inputs
if event.type == pygame.KEYDOWN: # * Checks key presses
if event.key == pygame.K_q: # * If Q is pressed
pygame.quit()
sys.exit()
elif event.key == pygame.K_s: # * Calls game loop again
game()
elif event.key == pygame.K_h:
screen.fill(bgcolor)
drawHelp(25, 70, 40)
# ! Game Loop
def game():
finished = False
done = False
# ! Spawn location of snake
x = sc_width / 2 # * Spawns snake at screen width / 2
x_move = 0 # * To update x coordinates as the snake moves
y = sc_height / 2 # * Spawns snake at screen height / 2
y_move = 0 # * To update y coordinates as the snake moves
score = 0
f = open('highscore.txt', 'r') # * Opens as read
highscore = int(f.readline())
f.close()
snakelist = []
snake_len = 1
# ! Randomizing apple spawn locations
apple_x = round(random.randrange(0, sc_width - 10) / 10.0) * 10.0
apple_y = round(random.randrange(0, sc_height - 10) / 10.0) * 10.0
while not finished:
while done == True:
screen.fill(bgcolor)
drawScore(snake_len - 1)
drawHighscore(highscore)
mainMenu()
# ! Movement input logic
for event in pygame.event.get(): # * Gathers inputs
if event.type == pygame.QUIT: # * If pygame.quit gets called (clicking X on window) it will set finished to True which will end game loop
finished = True # * Ends game loop
sys.exit()
if event.type == pygame.KEYDOWN: # * Checks if a key is pressed down
if event.key == pygame.K_d: # * If key 'D' is pressed increase x by 10 making it move right
x_move = 10 # * Speed it moves
y_move = 0 # * No vertical movement
elif event.key == pygame.K_a: # * If key 'A' is pressed decrease x by -10 making it move left
x_move = -10 # * Speed it moves
y_move = 0 # * No vertical movement
elif event.key == pygame.K_w: # * If key 'W' is pressed decrease y by -10 making it move up
x_move = 0 # * No horizontal movement
y_move = -10 # * Speed it moves
elif event.key == pygame.K_s: # * If key 'S' is pressed increase y by 10 making it move down
x_move = 0 # * No horizontal movement
y_move = 10 # * Speed it moves
# ! Out of bounds logic
# * If snake is at a value higher than screen res or lower than 0; it means its outside the screen box, then the Game loop var will be True and game ends
if x >= sc_width or x < 0 or y >= sc_height or y < 0:
done = True
# ! Update movement
x += x_move
y += y_move
screen.fill(bgcolor)
# ! Draw grid
Grid() # * Draws grid
# ! Draw snake and apples
pygame.draw.rect(screen, red, [apple_x, apple_y, 10, 10]) # * Draws apples on screen with red color and puts it at apple_x,y with size of 10
pygame.draw.rect(screen, yellow, [x, y, 10, 10]) # * Draws snake on screen with yellow color and puts it at var x,y with a size of 10
snakeH = []
snakeH.append(x) # * Appends snake head x position
snakeH.append(y) # * Appends snake head y position
snakelist.append(snakeH) # * Adds snake head to THE snake list
if len(snakelist) > snake_len: # * If snake list is bigger than snake length
del snakelist[0] # * Kills head
for x1 in snakelist[:-1]:
# ? Tried to understand this by using prints and seeing values:
# ? I'm guessing since it checks each block (prints show list with values with 10 seperating (size of block))
# ? DOES NOT PRINT HEAD
# ? If head hits one of the other boxes, it will overlap in list and head wont be skipped and it dies
# ! print(snakelist[:-1]) (Bugtesting / code understanding)
if x1 == snakeH:
# ! print(snakelist[:-1]) (Bugtesting / code understanding)
done = True
Snake(snake_block, snakelist) # * Updates func with new values
drawScore(snake_len - 1) # * - 1 because dont want to count head as a point
drawHighscore(highscore)
# ! Snake eating apple and growing
if x == apple_x and y == apple_y: # * Checks if snake is at apple pos
apple_x = round(random.randrange(0, sc_width - 10) / 10.0) * 10.0 # * Spawns new apple inside play area
apple_y = round(random.randrange(0, sc_height - 10) / 10.0) * 10.0 # * Spawns new apple inside play area
snake_len += 1 # * Increases snake length by 1
score += 1 # * Increases score by 1
# ! Saving highscore
f = open("highscore.txt", 'r+') # * Opens Highscore
highscore = int(f.readline()) # * Reads Highscore
if highscore > score: # * If Highscore > score(that run)
f.close() # * Close file
else: # * But if score > highscore
f.close # * Close it so it doesnt add to existing number ex: highscore: 5 score that run 6 = highscore: 56
f = open("highscore.txt", 'w') # * Open as write so it writes a new number
f.write(f'{score}') # * Write current score
f.close() # * Close
f = open('highscore.txt', 'r') # * Opens as read
highscore = int(f.readline())
f.close() # * Close file
# ! Setting FPS
clock.tick(30) # * Sets FPS to 30
pygame.display.update()
pygame.quit() # * Uninitializes pygame
quit() # * Quits
while True:
mainMenu()
I have modified your drawHelp function as follows:
def drawHelp(x, y, fsize):
help = "Controls: [W][A][S][D]\nInstructions: \nUse WASD to control the snake.\nGrab as many apples as you can;\nand dont crash into yourself :)\n\n [ (B) A C K ]"
hlp = help.splitlines()
for i, l in enumerate(hlp):
screen.blit(font.render(l, 0, white), (x, y + fsize*i))
pygame.display.update()
# to stay in this function until the B key is pressed.
b_pressed = False
while not b_pressed:
for event in pygame.event.get():
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_b:
b_pressed = True
Note I also had to add pygame.display.update() to the end of drawMenu() to make the main menu appear.
That said, there are several problems that make it harder for you to extend an debug your code. Typically pygame.display.update() should only be called once, also events should ideally be handled in one place. Event handlers would ideally modify the game state, e.g. change state from Main Menu to Help. Your event handlers call functions that take over event handling and drawing and updates. In order to achieve your outcome without refactoring your code, I've followed a similar practice.
It would probably help you to read up on state machines, here's an answer that may help you, or a pygame example whose use I imagine isn't strictly permitted for your homework. You've already started down this path with your done and finished variables.

My screen glitches out when I try to run my subprogram code

I'm working on a subprogram code that will make this happy face bounce around the screen and turn different colours. For some reason, the screen turns into that black glitchy screen and when I press exit at the top the face shows for a quick second before the program shuts down. I can't figure out why this is, here is my code and I've included a picture of what happens at first when I run it:
""" Program to show a very basic function
Most of the program is exactly the same as other programs we have done
The main difference is the grouping of code into a function called
drawHappy() to draw a few shapes together
In the main loop we "call" this function whenever we want to draw this
group of shapes
"""
# import the necessary modules
import pygame
import sys
import math
import random
from random import randint
# initialize pygame
pygame.init()
# set the size for the surface (screen)
# note this screen is resizable by the user
screen = pygame.display.set_mode((800, 600), pygame.RESIZABLE)
# set the caption for the screen
pygame.display.set_caption("Happy Face")
#screen width and height
screenW = screen.get_width()
screenH = screen.get_height()
# define colours you will be using
WHITE = (255, 255, 255)
GREEN = (0, 255, 0)
RED = (255, 0, 0)
BLUE = (0, 0, 255)
BLACK = (0, 0, 0)
YELLOW = (255, 255, 0)
# funtion to draw a the "happy face"
# it has 4 parameters passed to it xPos, yPos, radius, and colour
# notice all the shapes are drawn "relative" to the xPos and yPos and the radius
def drawHappy(xPos,yPos,r,colour):
pygame.draw.circle(screen,colour,(xPos,yPos),r,1)
eyeRadius = int(1/6*r)
eyeX = int(xPos-1/3*r)
eyeY = int(yPos- 1/3*r)
pygame.draw.circle(screen,colour,(eyeX,eyeY),eyeRadius,1)
eyeX = int(xPos + 1/3*r)
pygame.draw.circle(screen,colour,(eyeX,eyeY),eyeRadius,1)
wMouth = 1.5*r
xMouth = xPos - 3/4*r
yMouth = yPos - 3/4*r
pygame.draw.arc(screen,colour,(xMouth,yMouth,wMouth,wMouth),math.pi,2*math.pi,1)
randomR = randint(1,300)
r = randomR
randomX = randint(r, 800-r)
randomY = randint(r, 600-r)
dx = 0
dy = 0
x = 100
y = 100
speed = 3
x2 = randomX
y2 = randomY
dx2 = speed
dy2 = -speed
colour_list = [YELLOW, BLACK, BLUE, RED, GREEN]
randomcolour = random.choice(colour_list)
colour = RED
# set up clock to control frames per second
clock = pygame.time.Clock()
FPS = 120
# set main loop to True so it will run
main = True
# main loop
while main:
for event in pygame.event.get(): # check for any events (i.e key press, mouse click etc.)
if event.type == pygame.QUIT: # check to see if it was "x" at top right of screen
main = False # set the "main" variable to False to exit while loop
clock.tick(FPS)
screen.fill(WHITE)
oldx = x
oldy = y
x += dx
y += dy
if x >= 800-r or x <= 0+r:
x = oldx
if y >= 600-r or y <= 0+r:
y = oldy
x2 += dx2
y2 += dy2
if x >= 800-r or x <= 0+r:
dx2 = -dx2
randomcolour = random.choice(colour_list)
colour = randomcolour
if y2 >= 600-r or y2 <= 0+r:
dy2 = -dy2
randomcolour = random.choice(colour_list)
colour = randomcolour
# "call" the function "drawHappy()" to draw the happy face
# this is where we would normally do a pygame.draw or a screen.blit()
# we are "passing" the function 4 values to use(x,y,radius, colour)
# it will use these to know where to draw the happy face
drawHappy(x2,y2,r,colour)
pygame.display.flip()
# quit pygame and exit the program (i.e. close everything down)
pygame.quit()
sys.exit()
First of all, you need to call your draw function inside the loop. Your current code shows only a glimpse of "drawing" because it gets executed once you exit the main loop.
So, put your drawHappy() inside of main loop:
while main:
for event in pygame.event.get(): # check for any events (i.e key press, mouse click etc.)
if event.type == pygame.QUIT: # check to see if it was "x" at top right of screen
main = False # set the "main" variable to False to exit while loop
drawHappy(x2,y2,r,colour)
pygame.display.update()
clock.tick(FPS)
screen.fill(WHITE)
Now you will get a random size "smiley" on the screen, But now it will move on exit only, for the same reason it wouldn't display earlier. Next thing is to make it bounce (move). For this you'll need some kind of update of the coordinates, just like you did in the last part of your code, except they also need to be updated during the loop, not after it.
I suggest making a Class because then it will be easier to manipulate the object.
Also, I found it easier to separate draw and update_coordinates code into separate functions and them call them from main loop for example.
Hope this helps, and if you need more help, ask.
Here, I made a quick solution using parts of your code, there is plenty room for improvement especially for update_smiley_position() method where you can control how "smiley" moves.
Also, if you need multiple objects, a list should be passed instead of single object.
import pygame as pg
import math
import random
pg.init()
clock = pg.time.Clock()
window = pg.display.set_mode((800, 600), pg.RESIZABLE)
pg.display.set_caption("Happy Face")
SCREEN_W = window.get_width()
SCREEN_H = window.get_height()
class Smiley:
def __init__(self, x, y, r, color):
self.x = x
self.y = y
self.r = r
self.color = color
self.create_smiley()
def create_smiley(self):
self.eye_radius = int(1/6 * self.r)
self.eye_x1 = int(self.x - 1/3 * self.r)
self.eye_x2 = int(self.x + 1/3 *self.r)
self.eye_y = int(self.y - 1/3 *self.r)
self.mouth_width = 1.5 * self.r
self.mouth_x = self.x - self.r * 0.75
self.mouth_y = self.y - self.r * 0.75
def draw_smiley(self, win):
pg.draw.circle(win, self.color, (self.x, self.y), self.r, 1)
pg.draw.circle(win, self.color, (self.eye_x1, self.eye_y), self.eye_radius, 1)
pg.draw.circle(win, self.color, (self.eye_x2, self.eye_y), self.eye_radius, 1)
pg.draw.arc(win, self.color, (self.mouth_x, self.mouth_y, self.mouth_width, self.mouth_width), math.pi, 2*math.pi, 1)
def update_smiley_position(self):
if self.x >= SCREEN_H - self.r or self.x <= 0 + self.r:
self.x = random.randint(100, 400)
else:
self.x += 5
if self.y >= SCREEN_W - self.r or self.y <= 0 + self.r:
self.y = random.randint(100, 400)
else:
self.y -= 5
self.create_smiley()
def draw(win, smiley):
win.fill(pg.Color("white"))
smiley.draw_smiley(win)
smiley.update_smiley_position()
pg.display.update()
def main_loop(win, smiley):
clock.tick(30)
for event in pg.event.get():
if event.type == pg.QUIT:
return False
draw(win, smiley)
return True
r = random.randint(1, 300)
x = random.randint(r, SCREEN_W - r)
y = random.randint(r, SCREEN_H - r)
smiley = Smiley(x, y, r, pg.Color("red"))
while main_loop(window, smiley):
pass
pg.quit()

Pygame: colliding rectangles with other rectangles in the same list

I have a list of 10 drawn rectangles (referenced as cubes in my script) that are affected by gravity. I made a simple collision system for them to stop when they hit the ground. How can I make it so when 2 cubes collide they stop falling like they do with the ground?
import pygame
import time
import random
pygame.init()
clock = pygame.time.Clock()
wnx = 800
wny = 600
black = (0,0,0)
grey = (75,75,75)
white = (255,255,255)
orange = (255,100,30)
wn = pygame.display.set_mode((wnx, wny))
wn.fill(white)
def cube(cx,cy,cw,ch):
pygame.draw.rect(wn, orange, [cx, cy, cw, ch])
def floor(fx,fy,fw,fh):
pygame.draw.rect(wn, grey, [fx, fy, fw, fh])
def main():
floory = 550
number = 30
cubex = [0] * number
cubey = [0] * number
cubew = 10
cubeh = 10
for i in range(len(cubex)):
cubex[i] = (random.randrange(0, 80)*10)
cubey[i] = (random.randrange(2, 5)*10)
gravity = -10
exit = False
while not exit:
for event in pygame.event.get():
if event.type == pygame.QUIT:
exit = True
for i in range(len(cubex)): #i want to check here if it collides with an other cube
if not (cubey[i] + 10) >= floory:
cubey[i] -= gravity
wn.fill(white)
floor(0,floory,800,50)
for i in range(len(cubex)):
cube(cubex[i], cubey[i], cubew, cubeh)
pygame.display.update()
clock.tick(5)
main()
pygame.quit()
quit()
Use pygame.Rect.colliderect to check if to rectangles are intersecting.
Create an rectangle (pygame.Rect) which defines the next position (area) of the cube:
cubeR = pygame.Rect(cubex[i], cubey[i] + 10, cubew, cubeh)
Find all intersecting rectangles
cl = [j for j in range(len(cubey)) if j != i and cubeR.colliderect(pygame.Rect(cubex[j], cubey[j], cubew, cubeh))]
And don't move (let further "fall") the cube if there is any() collision:
if not any(cl):
# [...]
The check may look like this:
for i in range(len(cubex)):
cubeR = pygame.Rect(cubex[i], cubey[i] + 10, cubew, cubeh)
cisect = [j for j in range(len(cubey)) if j != i and cubeR.colliderect(pygame.Rect(cubex[j], cubey[j], cubew, cubeh))]
if not any(cisect) and not (cubey[i] + 10) >= floory:
cubey[i] -= gravity
Note, since all the cubes are aligned to an 10*10 raster, it is sufficient to check if the origins of the cubes are equal:
for i in range(len(cubex)):
cisect = [j for j in range(len(cubey)) if j != i and cubex[i] == cubex[j] and cubey[i]+10 == cubey[j]]
if not any(cisect) and not (cubey[i] + 10) >= floory:
cubey[i] -= gravity

Python Pygame randomly draw non overlapping circles

Im very new to python and seem to be missing something.
I want to randomly draw circles on a pygame display but only if the circles don't overlap each other.
I believe I must find the distance between all circle centers and only draw it if the distance is bigger than circle radius * 2.
I've tried many different things but all without success, I always get the same result - circles drawn overlapping.
#!/usr/bin/env python
import pygame, random, math
red = (255, 0, 0)
width = 800
height = 600
circle_num = 10
tick = 2
speed = 5
pygame.init()
screen = pygame.display.set_mode((width, height))
class circle():
def __init__(self):
self.x = random.randint(0,width)
self.y = random.randint(0,height)
self.r = 100
def new(self):
pygame.draw.circle(screen, red, (self.x,self.y), self.r, tick)
c = []
for i in range(circle_num):
c.append('c'+str(i))
c[i] = circle()
for j in range(len(c)):
dist = int(math.hypot(c[i].x - c[j].x, c[i].y - c[j].y))
if dist > int(c[i].r*2 + c[j].r*2):
c[j].new()
pygame.display.update()
else:
continue
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
You did not check against all other circles. I added a variable shouldprint which gets set to false if any other circle is too close.
import pygame, random, math
red = (255, 0, 0)
width = 800
height = 600
circle_num = 20
tick = 2
speed = 5
pygame.init()
screen = pygame.display.set_mode((width, height))
class circle():
def __init__(self):
self.x = random.randint(0,width)
self.y = random.randint(0,height)
self.r = 100
def new(self):
pygame.draw.circle(screen, red, (self.x,self.y), self.r, tick)
c = []
for i in range(circle_num):
c.append('c'+str(i))
c[i] = circle()
shouldprint = True
for j in range(len(c)):
if i != j:
dist = int(math.hypot(c[i].x - c[j].x, c[i].y - c[j].y))
if dist < int(c[i].r*2):
shouldprint = False
if shouldprint:
c[i].new()
pygame.display.update()
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
The for loop has been changed to a while loop. It will keep trying to generate circles until the target number is reached. A circle is first generated. Then, it checks if it intersects with any existing circle using the formula from this answer.
It iterates through every existing circle (store in the list circles) and performs the check using the formula. any() returns True if the formula evaluates to True for any iteration. If it's True, it means it found an intersection. Thus, it continues to the next iteration to try again with a new circle.
circles = []
while len(circles) < circle_num:
new = circle()
if any(pow(c.r - new.r, 2) <=
pow(c.x - new.x, 2) + pow(c.y - new.y, 2) <=
pow(c.r + new.r, 2)
for c in circles):
continue
circles.append(new)
new.new()
pygame.display.update()

pygame: Stopping movement behind line

I am attempting to create a game that lets a block move "jump" and land on a platform above it. Then, jump again to the next platform.
Unfortunately, my code currently just stops when the block touches the bottom of the platform and moves no further. I am unsure why as i believe it should only stop when the bottom of the block hits the line
Specifically am looking at this bit of code, but full code below for context:
#the floor landing code
def hasJumperLanded(rect1, rect2):
for a, b in [(rect1, rect2), (rect2, rect1)]:
if isFloorTouching(a.bottom, b):
return True
def isFloorTouching(y, rect):
if (y > rect.top) and (y < rect.bottom):
return True
else:
return False
snip
#stop when land on floor
for n in range(len(floors)):
if (hasJumperLanded(j['rect'], floors[n]['line'])):
j['jump'] = STILL
Full code context:
import pygame, sys, time
from pygame.locals import *
#the deadzone collision code
def doRectsOverlap(rect1, rect2):
for a, b in [(rect1, rect2), (rect2, rect1)]:
if ((isPointInsideRect(a.left, a.top, b)) or
(isPointInsideRect(a.left, a.bottom, b)) or
(isPointInsideRect(a.right, a.top, b)) or
(isPointInsideRect(a.right, a.bottom, b))):
return True
return False
def isPointInsideRect(x, y, rect):
if (x > rect.left) and (x < rect.right) and (y > rect.top) and (y < rect.bottom):
return True
else:
return False
#the floor landing code
def hasJumperLanded(rect1, rect2):
for a, b in [(rect1, rect2), (rect2, rect1)]:
if isFloorTouching(a.bottom, b):
return True
def isFloorTouching(y, rect):
if (y > rect.top) and (y < rect.bottom):
return True
else:
return False
# set up pygame
pygame.init()
mainClock = pygame.time.Clock()
# set up the window
WINDOWWIDTH = 480
WINDOWHEIGHT = 800
windowSurface = pygame.display.set_mode((WINDOWWIDTH, WINDOWHEIGHT), 0, 32)
pygame.display.set_caption('Jumper')
#Directions
LEFT = 4
RIGHT = 6
UP = 8
DOWN = 2
STILL = 5
#blocks location for jumping
#BLOCKLOCY = 700
#Binary for stopping movement
#STOPPER = 0
MOVESPEED = 1
# set up the colors
BLACK = (0, 0, 0)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)
j = {'rect':pygame.Rect(240, 700, 20, 20), 'color':GREEN, 'dir':LEFT, 'jump':STILL}
f1 = {'line':pygame.Rect(0,720,480,2), 'color':GREEN, 'dir':STILL}
f2 = {'line':pygame.Rect(0,650,480,2), 'color':GREEN, 'dir':STILL}
floors = [f1,f2]
# run the game loop
while True:
# check for the QUIT event
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
# draw the black background onto the surface
windowSurface.fill(BLACK)
# This way or that way. Speed Code
if j['dir'] == LEFT:
j['rect'].left -= MOVESPEED
if j['dir'] == RIGHT:
j['rect'].left += MOVESPEED
#JUST JUMP ALREADY!
if j['jump'] == UP:
j['rect'].bottom -= MOVESPEED
#BLOCKLOCY -= MOVESPEED
#Bouce when side hitting
if j['rect'].left < 0:
j['dir'] = RIGHT
if j['rect'].left > WINDOWWIDTH-j['rect'].width:
j['dir'] = LEFT
#Press to Jump
if event.type == KEYDOWN:
if event.key == K_SPACE:
j['jump'] = UP
#stop when land on floor
for n in range(len(floors)):
if (hasJumperLanded(j['rect'], floors[n]['line'])):
j['jump'] = STILL
#Floor controll code for moving level - not working currently
for f in floors:
#if f['dir'] == DOWN:
# f['line'].y += MOVESPEED
# if event.type == KEYDOWN:
# if event.key == K_SPACE:
# f['dir'] = DOWN
# if f['line'].top == BLOCKLOCY:
# f['dir'] = STILL
# STOPPER = 1
#if f['line'].bottom == BLOCKLOCY:
# f['dir'] = STILL
# STOPPER = 1
# draw the block onto the surface
pygame.draw.rect(windowSurface, j['color'], j['rect'])
pygame.draw.rect(windowSurface, f['color'], f['line'])
# draw the window onto the screen
pygame.display.update()
mainClock.tick(1000)
#the floor landing code
def hasJumperLanded(rect1, rect2):
for a, b in [(rect1, rect2), (rect2, rect1)]: ## **
if isFloorTouching(a.bottom, b):
return True
Take a look at the line I marked in this snippet.
Here You are checking the rects to collide both ways.
So you loose the meaning of which one is the floor and which one is moving.
If you just check (rect1, rect2) you will see the difference.
--
EDIT:
Check this out
def hasJumperLanded(rect1, rect2):
for a, b in [(rect1, rect2), (rect2, rect1)]:
if isFloorTouching(rect1, rect2):
return True
def isFloorTouching(y, rect):
if (y.bottom > rect.top) and (y.bottom < rect.bottom):
return True
else:
return False
It is more logical to handle the meaning of the floor inside the isFloorTouching() function.

Categories