this program makes boxes move, but i need to make them move randomly and indepensent of each other,
by calling the method "rect.move()" for each of the boxes but i don't know how to do that can u help me.
ex. of how it should not look like: https://youtu.be/D7rkcA0-BR0
import pygame
import random
# Define some colors
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
GREEN = (0, 255, 0)
RED = (255, 0, 0)
class Rect():
def __init__(self):
self.rectXPos = 0
self.rectYPos = 0
self.height = 0
self.width = 0
self.changeX = 0
self.changeY = 0
self.x = 0
self.y = 0
def move(self):
self.x += self.changeX
self.y += self.changeY
def draw(self,screen):
pygame.draw.rect(screen,RED,[self.x + self.rectXPos, self.y + self.rectYPos, self.height,self.width])
pygame.init()
# Set the width and height of the screen [width, height]
size = (700, 500)
screen = pygame.display.set_mode(size)
pygame.display.set_caption("My Game")
# Loop until the user clicks the close button.
done = False
# Used to manage how fast the screen updates
clock = pygame.time.Clock()
myList =[]
for i in range(10):
rect = Rect()
rect.rectXPos = random.randrange(0,700)
rect.rectYPos = random.randrange(0,500)
rect.height = random.randrange(20,70)
rect.width = random.randrange(20,70)
rect.changeX = random.randrange(-3,3)
rect.changeY = random.randrange(-3,3)
myList.append([rect.rectXPos , rect.rectYPos, rect.height, rect.width, rect.changeX, rect.changeY])
# -------- Main Program Loop -----------
while not done:
# --- Main event loop
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
# --- Game logic should go here
# --- Screen-clearing code goes here
# Here, we clear the screen to white. Don't put other drawing commands
# above this, or they will be erased with this command.
# If you want a background image, replace this clear with blit'ing the
# background image.
screen.fill(WHITE)
for i in range(10):
rect.rectXPos = myList[i][0]
rect.rectYPos = myList[i][1]
rect.height = myList[i][2]
rect.width = myList[i][3]
rect.changeX = myList[i][4]
rect.changeY= myList[i][5]
rect.draw(screen)
rect.move()
# --- Drawing code should go here
# --- Go ahead and update the screen with what we've drawn.
pygame.display.flip()
# --- Limit to 60 frames per second
clock.tick(60)
# Close the window and quit.
pygame.quit()
this is premade code from http://programarcadegames.com/
What you need is for the Rect attributes to be randomly generated with the random module. I have modified the code you gave an made some changes.
Firstly I changed the draw method so that it just draws at the x and y values.
The biggest change was that instead of the big complicated myList list in your code, I just stored 10 Rect objects in a list called myRects which I think is much simpler.
You can fiddle around some more with the number generation from around Line 45-52. You can read a bit more on the random.randrange() function here: https://docs.python.org/3/library/random.html#functions-for-integers
I hope this answer helped you! If you have any further questions please post a comment below!
import pygame
import random
# Define some colors
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
GREEN = (0, 255, 0)
RED = (255, 0, 0)
class Rect():
def __init__(self):
self.x = 0
self.y = 0
self.height = 0
self.width = 0
self.changeX = 0
self.changeY = 0
def move(self):
self.x += self.changeX
self.y += self.changeY
def draw(self, screen):
pygame.draw.rect(screen, RED, [self.x, self.y, self.width, self.height], 0)
pygame.init()
size = (700, 500)
screen = pygame.display.set_mode(size)
pygame.display.set_caption("My Game")
done = False
clock = pygame.time.Clock()
myRects = []
for i in range(10):
rect = Rect()
rect.x = random.randrange(0, 700)
rect.y = random.randrange(0, 700)
rect.width = random.randrange(20, 70)
rect.height = random.randrange(20, 70)
rect.changeX = random.randrange(-3, 3)
rect.changeY = random.randrange(-3, 3)
myRects.append(rect)
print(myRects)
while not done:
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
screen.fill(WHITE)
for rect in myRects:
rect.draw(screen)
rect.move()
pygame.display.update()
clock.tick(10)
pygame.quit()
quit()
Related
I making a small game with multiple falling cubes and the player(the square) has to avoid it. I manage to get the collision to work but the problem is when every time the circle and square collide it displays the text every time they collide. But I want the text to stay on when the circle and square first collide. Is there any way to do that?
import pygame
from pygame.locals import *
import os
import random
import math
import sys
import time
white = (255,255,255)
blue = (0,0,255)
gravity = 10
size =10
height = 500
width =600
varHeigth = height
ballNum = 5
eBall = []
apGame = pygame.display.set_mode((width, height))
pygame.display.set_caption("AP Project")
clock = pygame.time.Clock()
class Player(object):
def __init__(self):
red = (255, 0, 0)
move_x = 300
move_y = 400
self.rect = pygame.draw.rect(apGame,red, (move_x, move_y, 10, 10))
self.dist = 10
def handle_keys(self):
for e in pygame.event.get():
if e.type == pygame.QUIT:
pygame.quit();
exit()
key = pygame.key.get_pressed()
if key[pygame.K_LEFT]:
self.draw_rect(-1, 0)
elif key[pygame.K_RIGHT]:
self.draw_rect(1, 0)
elif key[pygame.K_ESCAPE]:
pygame.quit();
exit()
else:
self.draw_rect(0, 0)
def draw_rect(self, x, y):
red = (255, 0, 0)
black = (0, 0, 0)
'''apGame.fill(black)'''
self.rect = self.rect.move(x * self.dist, y * self.dist);
pygame.draw.rect(apGame, red , self.rect)
pygame.display.update()
def draw(self,surface):
red = (255, 0, 0)
move_x = 300
move_y = 400
pygame.draw.rect(apGame, red, (move_x, move_y, 10, 10))
#The game over text here
def show_go_screen():
pygame.font.init()
myfont = pygame.font.SysFont("Comic Sans MS", 30)
label = myfont.render("Game Over", 1, red)
apGame.blit(label, (300,100))
def instuct():
pygame.font.init()
myfont = pygame.font.SysFont("Comic Sans MS", 15)
label = myfont.render("Avoid The Circles", 1, red)
apGame.blit(label, (250,450))
'''game_over = False'''
move_x = 300
move_y = 400
red = (255, 0, 0)
black = (0, 0, 0)
player = Player()
clock = pygame.time.Clock()
'''apGame.fill(black)'''
player.draw(apGame)
pygame.display.update()
for q in range(ballNum):
x = random.randrange(0, width)
y = random.randrange(0, varHeigth)
eBall.append([x, y])
while True:
apGame.fill(black)
for i in range(len(eBall)):
ball_rect = pygame.draw.circle(apGame, blue, eBall[i], size)
#where the code is supposed to work
if player.rect.colliderect(ball_rect):
'''game_over = True'''
show_go_screen()
eBall[i][1] += 5
if eBall[i][1] > height:
y = random.randrange(-50, -10)
eBall[i][1] = y
x = random.randrange(0, width)
eBall[i][0] = x
instuct()
player.handle_keys()
pygame.display.flip()
clock.tick(30)
Whenever you want functionality to only run once, you should add a check outside of that function to make sure the code within that function only runs once. Here's an example of that using your code.
collidedOnce = False
if player.rect.colliderect(ball_rect):
if(collidedOnce == False):
collidedOnce = True #This makes the code only run once since it's setting this variable to be true within the condition
#game_over = True
show_go_screen()
eBall[i][1] += 5
if eBall[i][1] > height:
y = random.randrange(-50, -10)
eBall[i][1] = y
x = random.randrange(0, width)
eBall[i][0] = x
instuct()
player.handle_keys()
pygame.display.flip()
clock.tick(30)
Hope this helps
I'm working from the book "Program Arcade Games
With Python And Pygame" and working through the 'lab' at the end of Chapter 12: Introduction to Classes.
This code I've written for it randomises the coordinates size and movement direction for each shape created in 'my_list' by calling its constructor but not the colour, all the shapes created have the same colour, why is this?
import pygame
import random
# Define some colors
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
GREEN = (0, 255, 0)
RED = (255, 0, 0)
class Rectangle():
x = 0
y = 0
width = 10
height = 10
change_x = 2
change_y = 2
color = [0, 0, 0]
def __init__(self):
self.x = random.randrange(0, 700)
self.y = random.randrange(0, 500)
self.change_x = random.randrange(-3., 3)
self.change_y = random.randrange(-3., 3)
self.width = random.randrange(20, 70)
self.height = random.randrange(20, 70)
for i in range(3):
self.color[i] = random.randrange(0, 256)
def draw(self, screen):
pygame.draw.rect(screen, self.color, [self.x, self.y, self.width, self.height], 0)
def move(self):
if self.x < 0:
self.change_x *= -1
if self.x > 700-self.width:
self.change_x *= -1
if self.y < 0:
self.change_y *= -1
if self.y > 500-self.height:
self.change_y *= -1
self.x += self.change_x
self.y += self.change_y
class Ellipse(Rectangle):
def draw(self, screen):
pygame.draw.ellipse(screen, self.color, [self.x, self.y, self.width, self.height], 0)
pygame.init()
# Set the width and height of the screen [width, height]
size = (700, 500)
screen = pygame.display.set_mode(size)
pygame.display.set_caption("My Game")
# Loop until the user clicks the close button.
done = False
# Used to manage how fast the screen updates
clock = pygame.time.Clock()
my_list = []
for i in range(10):
my_list.append(Rectangle())
for i in range(10):
my_list.append(Ellipse())
# -------- Main Program Loop -----------
while not done:
# --- Main event loop
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
# --- Game logic should go here
# --- Screen-clearing code goes here
# Here, we clear the screen to white. Don't put other drawing commands
# above this, or they will be erased with this command.
# If you want a background image, replace this clear with blit'ing the
# background image.
screen.fill(WHITE)
# --- Drawing code should go here
for shape in my_list:
shape.draw(screen)
shape.move()
# --- Go ahead and update the screen with what we've drawn.
pygame.display.flip()
# --- Limit to 60 frames per second
clock.tick(60)
# Close the window and quit.
pygame.quit()```
The instance attribute self.color is never created. The existing variable color is a class attribute. Read about the difference of Class and Instance Variables. A class attribute exists only once and (of course) has the same value in each instance when it is read. An instance variable exists per instance of the class and can have a different value in each instance.
Create the list of color channels by:
class Rectangle():
def __init__(self):
# [...]
self.color = [0, 0, 0]
for i in range(3):
self.color[i] = random.randrange(0, 256)
respectively
class Rectangle():
def __init__(self):
# [...]
self.color = [random.randrange(0, 256) for _ in range(3)]
This code is mostly just the generic start up of a pygame window but I'm trying to make it so the object moves (the planet object I've made) in the orbit around the sun object I've made for the coordinates I've given it. I know the x and y values are updating but I don't understand why the object doesn't move.
#import the library
import pygame
import math
#classes
class button:
def _init_ (self,screen, colour, x, y, width,height, letter):
self.screen = screen
self.colour = colour
self.x = x
self.y = y
self.width = width
self.height = height
self.letter = letter
self.radius = radius
def draw(self):
pygame.draw.rect(self.screen, self.colour,(self.x,self.y, self.width, self.height))
if self.letter!= '+' and self.letter!= '-':
font = pygame.font.SysFont('agencyfb',15,True,False)
else:
font = pygame.font.SysFont('agencyfb',25,True,False)
text = font.render(self.letter, True, black)
text_rect = text.get_rect(center=(self.x+self.width/2,self.y+self.height/2))
screen.blit(text, text_rect)
class orbit:
def __init__(self,screen,colour,x,y,radius,width):
self.screen = screen
self.colour = colour
self.x = x
self.y = y
self.width = width
self.radius = radius
def draw_circle(self):
pygame.draw.circle(self.screen,self.colour,(self.x,self.y),self.radius,self.width)
#define colours
##Sun = pygame.draw.circle(screen,Sun,[1000,450],100,0)
Black = (0,0,0)
White = (255,255,255)
Green = (0,255,0)
Red = (255,0,0)
Blue = (0,0,255)
Sun = (255,69,0)
Sun = []
Planet = []
#initialise the engine
pygame.init()
#Opening a window
size = (1920,1080)
screen = pygame.display.set_mode(size)
#set window title
pygame.display.set_caption("Orbit Simulator")
#loop unti the user clicks the close button
done = False
#
x=1000
y=450
Sun.append(orbit(screen,Red,1000,450,100,0))
Planet.append(orbit(screen,White,x,y,50,0))
#
#used to manage how fast the screen updates
clock = pygame.time.Clock()
#------ Main program Loop ------
while not done:
#--- Main event loop
for event in pygame.event.get(): #user did something
if event.type == pygame.QUIT: #if user clicked close
done = True #flag that we are done and exit the loop
#------ Game logic should go here ------
#------ Drawing code should go here -------
#first, clear the screen to white. Don't put other drawing commands above this or they will be erased with this command.
screen.fill(Black)
for i in Sun:
i.draw_circle()
for i in Planet:
r=150
angle=0
count = 0
while angle <= 360:
angle_radians = math.radians(angle)
x = int(math.cos(angle_radians)*r)
y = int(math.sin(angle_radians)*r)
angle +=1
count +=1
print(count)
x+=1000
y+=450
pygame.draw.circle(screen,White,[x,y],10,0)
print("Position [",x,",",y,"]")
#update the screen
pygame.display.flip()
#------ Limit to 60 frames per second ------
clock.tick(60)
#------ When the loop ends, quit ------
pygame.quit()
You can make an object rotate around another by using trigonometry or vectors. With vectors you just have to rotate a vector which defines the offset from the rotation center each frame and add it to the position vector (self.pos which is the rotation center) to get the desired self.rect.center coordinates of the orbiting object.
import pygame as pg
from pygame.math import Vector2
class Planet(pg.sprite.Sprite):
def __init__(self, pos, *groups):
super().__init__(*groups)
self.image = pg.Surface((40, 40), pg.SRCALPHA)
pg.draw.circle(self.image, pg.Color('dodgerblue'), (20, 20), 20)
self.rect = self.image.get_rect(center=pos)
self.pos = Vector2(pos)
self.offset = Vector2(200, 0)
self.angle = 0
def update(self):
self.angle -= 2
# Add the rotated offset vector to the pos vector to get the rect.center.
self.rect.center = self.pos + self.offset.rotate(self.angle)
def main():
pg.init()
screen = pg.display.set_mode((640, 480))
screen_rect = screen.get_rect()
clock = pg.time.Clock()
all_sprites = pg.sprite.Group()
planet = Planet(screen_rect.center, all_sprites)
yellow = pg.Color('yellow')
while True:
for event in pg.event.get():
if event.type == pg.QUIT:
return
all_sprites.update()
screen.fill((30, 30, 30))
pg.draw.circle(screen, yellow, screen_rect.center, 60)
all_sprites.draw(screen)
pg.display.flip()
clock.tick(60)
if __name__ == '__main__':
main()
pg.quit()
I need help with my programming assignment. I need to make it so the blocks in the game bounce off of each other when the collide. The code below uses Pygame. I've been trying to do this for a couple hours now and keep running into walls.
import pygame
from pygame.locals import *
import time
class Block:
def __init__(self,win,left,top,
width,height,color,velocity):
self.win = win
self.rect = pygame.Rect(left,top,
width,height)
self.color = color
self.velocity = velocity
def move(self):
self.rect = self.rect.move(
self.velocity[0],self.velocity[1])
if ((self.rect.top < 0) or
(self.rect.bottom > self.win.height)):
self.velocity[1] = -self.velocity[1]
if ((self.rect.left < 0) or
(self.rect.right > self.win.width)):
self.velocity[0] = -self.velocity[0]
def tupleRep(block):
return ((block.rect.left, block.rect.top),(block.rect.right, block.rect.bottom))
colliderect()
def draw(self):
pygame.draw.rect(self.win.surface,
self.color, self.rect,0)
class BlockWindow:
def __init__(self,width,height,caption):
self.surface = pygame.display.set_mode((width,height))
self.caption = caption
pygame.display.set_caption(self.caption)
self.height = height
self.width = width
self.blocks = [ ]
self.blocks.append(Block(self,300,80,50,
100,RED,[BASESPEED,-BASESPEED]))
self.blocks.append(Block(self,200,200,20,
20,GREEN,[-BASESPEED,-BASESPEED]))
self.blocks.append(Block(self,100,150,60,
60,BLUE,[-BASESPEED,BASESPEED]))
self.blocks.append(Block(self,100,100,70,
200,PURPLE,[BASESPEED,BASESPEED]))
self.blocks.append(Block(self,300,70,50,
60,TEAL,[-BASESPEED,BASESPEED]))
Quit = False
while not Quit:
self.surface.fill(BLACK)
for b in self.blocks:
b.move()
b.draw()
pygame.display.update()
time.sleep(0.02) #import what for this?
for event in pygame.event.get():
if event.type == QUIT:
Quit = True
# set up the colors
BLACK = (0, 0, 0)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)
PURPLE= (200,0,200)
TEAL = (0,200,200)
BASESPEED = 2
# set up pygame
pygame.init()
win = BlockWindow(800,800,'Animation with Objects')
pygame.quit()
Here is the most I can help you without preventing you from learning anything:
http://www.pygame.org/docs/ref/sprite.html
http://www.pygame.org/docs/ref/sprite.html#pygame.sprite.spritecollide
http://www.pygame.org/docs/ref/sprite.html#pygame.sprite.collide_rect
http://www.pygame.org/docs/ref/sprite.html#pygame.sprite.collide_circle
Also try the book "Hello World!" by Carter and Warren Sande.
I am trying to make a moving platform so when the platforms reaches a curtain point it is supposed to reverse direction and go back but from what I can see it looks like it is vibrating back and fort
program link: https://drive.google.com/file/d/0BzvvQCByWwmAQThfdkEtSlRKa1k/view?usp=sharing
here is my code:
class lbuild(pygame.sprite.Sprite):
#This class represents alevel builder. It derives from the "Sprite" class in Pygame.
def __init__(self, color, width, height,x,y):
# Call the parent class (Sprite) constructor
super().__init__()
self.image = pygame.Surface([width, height])
self.image.fill(WHITE)
self.image.set_colorkey(WHITE)
# Draw the car (a rectangle!)
pygame.draw.rect(self.image, color, [0, 0, width, height])
# Fetch the rectangle object that has the dimensions of the image.
self.rect = self.image.get_rect()
self.rect.x=x
self.rect.y=y
all_sprites_list = pygame.sprite.Group()
movblock=pygame.sprite.Group()#sprite group
def level1():
global all_sprites_list
global movblock
xpos=0
for x in range(50):
all_sprites_list.add(lbuild(GREY,20,20,xpos,680))
xpos =xpos+20
ypos=660
xpos2 =40
for x in range(2):
all_sprites_list.add(lbuild(black,60,20,xpos2,ypos))
ypos=ypos-20
mblk=lbuild(RED,100,20,120,600)#draws the block
movblock.add(mblk)#adds it to the sprite group
clock=pygame.time.Clock()
while True:
for event in pygame.event.get():
if event.type==QUIT:
pygame.quit()
sys.exit()
#Game Logic
all_sprites_list.update()
#Drawing on Screen
screen.fill(WHITE)
#Draw The Road
spd=5
if mblk.rect.x>200:#supposed to cheak if the block x postion a has reached 200 and the reverse its direction but instead it looks like it is vibrating
spd= -spd
if mblk.rect.x<100:
spd= -spd
mblk.rect.x+=spd
#Now let's draw all the sprites in one go. (For now we only have 1 sprite!)
all_sprites_list.draw(screen)
movblock.draw(screen)
#Refresh Screen
pygame.display.flip()
#Number of frames per secong e.g. 60
clock.tick(60)
Your problem is spd = 5 inside while True.
You change direction using
spd = -spd
but after that you overwrite it using
spd = 5
You have to use spd = 5 before while True
Full version with other modifications.
import pygame
import sys
# --- constants --- (UPPER_CASE names)
WHITE = (255, 255, 255)
GREEN = (20, 255, 140)
GREY = (210, 210 ,210)
WHITE = (255, 255, 255)
RED = (255, 0, 0)
PURPLE = (255, 0, 255)
BLACK = (0,0,0)
SCREEN_WIDTH=1000
SCREEN_HEIGHT=700
# --- classes --- (CamelCase names)
class LBuild(pygame.sprite.Sprite):
def __init__(self, color, width, height, x, y):
super().__init__()
self.image = pygame.Surface([width, height])
self.image.fill(WHITE)
self.image.set_colorkey(WHITE)
# Draw the car (a rectangle!)
pygame.draw.rect(self.image, color, [0, 0, width, height])
# Fetch the rectangle object that has the dimensions of the image.
self.rect = self.image.get_rect()
self.rect.x = x
self.rect.y = y
# --- functions --- (lower_case names)
def level_1(screen, all_sprites_list, movblock):
x = 0
for _ in range(50):
all_sprites_list.add(LBuild(GREY, 20, 20, x, 680))
x += 20
y = 660
x2 = 40
for _ in range(2):
all_sprites_list.add(LBuild(BLACK, 60, 20, x2, y))
y -= 20
mblk = LBuild(RED, 100, 20, 120, 600)
movblock.add(mblk)
spd = 5
# - mainloop -
clock = pygame.time.Clock()
#current_time = pygame.time.get_ticks()
# change something after 2s
#change_time = current_time + 2000 # 2000ms = 2s
while True:
# - events -
for event in pygame.event.get():
if event.type == pygame.QUIT:
# False = exit game
return False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
# True = go to next level
return True
# - updates (without draws) -
#current_time = pygame.time.get_ticks()
#if current_time >= change_time:
# TODO: change something
# # change something again after 2s
# change_time = current_time + 2000
all_sprites_list.update()
if mblk.rect.x > 200:
spd = -spd
if mblk.rect.x < 100:
spd = -spd
mblk.rect.x += spd
# - draws (without updates) -
screen.fill(WHITE)
all_sprites_list.draw(screen)
movblock.draw(screen)
pygame.display.flip()
# - FPS -
clock.tick(60)
# --- main ---
# - init -
pygame.init()
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
pygame.display.set_caption("Car Racing")
# - game -
all_sprites_list = pygame.sprite.Group()
movblock = pygame.sprite.Group()
goto_next_level = level_1(screen, all_sprites_list, movblock)
#if goto_next_level:
# goto_next_level = level_2(screen, all_sprites_list, movblock)
#if goto_next_level:
# goto_next_level = level_3(screen, all_sprites_list, movblock)
# - exit -
pygame.quit()
sys.exit()