I am trying to make a game where you can shoot bullets to kill emojis. However, i can't manage to figure out how to stop spamming the space key to shoot bullets. If you keep on spamming, the game would be too easy. I am not exactly sure if what command I should use. Please help! thanks!
Here is my code:
# import everything from turtle
from turtle import *
import random
import math
#create a link to the object (creates the environment)
screen = Screen()
speed1 = 1.3
ht()
amountOfEmojis = 11
#set a boundary for screen, if touches end, goes to the other side
screenMinX = -screen.window_width()/2
screenMinY = -screen.window_height()/2
screenMaxX = screen.window_width()/2
screenMaxY = screen.window_height()/2
#establish important data for screen environment
screen.setworldcoordinates(screenMinX,screenMinY,screenMaxX,screenMaxY)
screen.bgcolor("black")
#turtle setup
penup()
ht()
speed(0)
goto(0, screenMaxY - 50)
color('white')
write("Welcome to Emoji Run!", align="center", font=("Courier New",26))
goto(0, screenMaxY - 70)
write("Use the arrow keys to move and space to fire. The point of the game is to kill the emojis", align="center")
goto(0, 0)
color("red")
emojis = ["Poop_Emoji_7b204f05-eec6-4496-91b1-351acc03d2c7_grande.png", "1200px-Noto_Emoji_KitKat_263a.svg.png",
"annoyningface.png", "Emoji_Icon_-_Sunglasses_cool_emoji_large.png"]
class Bullet(Turtle):
#constructor, object for a class, pass in information
def __init__(self,screen,x,y,heading):
#create a bullet
Turtle.__init__(self)#clones bullet
self.speed(0)
self.penup()
self.goto(x,y)
self.seth(heading)#pointing to itself
self.screen = screen
self.color('yellow')
self.max_distance = 500
self.distance = 0
self.delta = 20
self.shape("bullet")
#logic to move bullet
def move(self):
self.distance = self.distance + self.delta#how fast it's going to move
self.forward(self.delta)
if self.done():
self.reset()
def getRadius(self):
return 4#collision detection helper function
def blowUp(self):
self.goto(-300,0)#function that makes something go off the screen
def done(self):
return self.distance >= self.max_distance # append to list
class Asteroid(Turtle):
def __init__(self,screen,dx,dy,x,y,size,emoji):#spawn asteroid randomly
Turtle.__init__(self)#clone itself
self.speed(0)
self.penup()
self.goto(x,y)
self.color('lightgrey')
self.size = size
self.screen = screen
self.dx = dx
self.dy = dy
r = random.randint(0, len(emoji) - 1)
screen.addshape(emojis[r])
self.shape(emojis[r])
#self.shape("rock" + str(size)) #sets size and shape for asteroid
def getSize(self):#part of collision detection
return self.size
#getter and setter functions
def getDX(self):
return self.dx
def getDY(self):
return self.dy
def setDX(self,dx):
self.dx = dx
def setDY(self,dy):
self.dy = dy
def move(self):
x = self.xcor()
y = self.ycor()
#if on edge of screen. go to opposite side
x = (self.dx + x - screenMinX) % (screenMaxX - screenMinX) + screenMinX
y = (self.dy + y - screenMinY) % (screenMaxY - screenMinY) + screenMinY
self.goto(x,y)
def blowUp(self):
self.goto(-300,0)#function that makes something go off the screen
def getRadius(self):
return self.size * 10 - 5
class SpaceShip(Turtle):
def __init__(self,screen,dx,dy,x,y):
Turtle.__init__(self)
self.speed(0)
self.penup()
self.color("white")
self.goto(x,y)
self.dx = dx
self.dy = dy
self.screen = screen
self.bullets = []
self.shape("turtle")
def move(self):
x = self.xcor()
y = self.ycor()
x = (self.dx + x - screenMinX) % (screenMaxX - screenMinX) + screenMinX
y = (self.dy + y - screenMinY) % (screenMaxY - screenMinY) + screenMinY
self.goto(x,y)
#logic for collision
def powPow(self, asteroids):
dasBullets = []
for bullet in self.bullets:
bullet.move()
hit = False
for asteroid in asteroids:
if intersect(asteroid, bullet):#counts every asteroid to see if it hits
asteroids.remove(asteroid)
asteroid.blowUp()
bullet.blowUp()
hit = True
if (not bullet.done() and not hit):
dasBullets.append(bullet)
self.bullets = dasBullets
def fireBullet(self):
self.bullets.append(Bullet(self.screen, self.xcor(), self.ycor(), self.heading()))
def fireEngine(self):#how turtle moves
angle = self.heading()
x = math.cos(math.radians(angle))
y = math.sin(math.radians(angle))
self.dx = self.dx + x#how it rotates
self.dy = self.dy + y
self.dx = self.dx / speed1
self.dy = self.dy / speed1
#extra function
def turnTowards(self,x,y):
if x < self.xcor():
self.left(7)
if x > self.xcor():
self.right(7)
def getRadius(self):
return 10
def getDX(self):
return self.dx
def getDY(self):
return self.dy
#collision detection
def intersect(object1,object2):
dist = math.sqrt((object1.xcor() - object2.xcor())**2 + (object1.ycor() - object2.ycor())**2)
radius1 = object1.getRadius()
radius2 = object2.getRadius()
# The following if statement could be written as
# return dist <= radius1+radius2
if dist <= radius1+radius2:
return True
else:
return False
#adds object to screen
screen.register_shape("rock3",((-20, -16),(-21, 0), (-20,18),(0,27),(17,15),(25,0),(16,-15),(0,-21)))
screen.register_shape("rock2",((-15, -10),(-16, 0), (-13,12),(0,19),(12,10),(20,0),(12,-10),(0,-13)))
screen.register_shape("rock1",((-10,-5),(-12,0),(-8,8),(0,13),(8,6),(14,0),(12,0),(8,-6),(0,-7)))
screen.register_shape("ship",((-10,-10),(0,-5),(10,-10),(0,10)))
screen.register_shape("bullet",((-2,-4),(-2,4),(2,4),(2,-4)))
#ship spawn exactly the middle everytime
ship = SpaceShip(screen,0,0,(screenMaxX-screenMinX)/2+screenMinX,(screenMaxY-screenMinY)/2 + screenMinY)
#randomize where they spawn
asteroids = []
for k in range(amountOfEmojis):
dx = random.random() * 6 - 3
dy = random.random() * 6 - 3
x = random.randrange(10) * (screenMaxX - screenMinX) + screenMinX
y = random.random() * (screenMaxY - screenMinY) + screenMinY
asteroid = Asteroid(screen,dx,dy,x,y,random.randint(1,3), emojis)
asteroids.append(asteroid)
def play():
# Tell all the elements of the game to move
ship.move()
gameover = False
for asteroid in asteroids:
r = random.randint(0, 1)
if r == 1:
asteroid.right(50)
else:
asteroid.left(20)
asteroid.move()
if intersect(ship,asteroid):
write("You Got Killed :(",font=("Verdana",25),align="center")
gameover = True
ship.powPow(asteroids)
screen.update()
if not asteroids:
color('green')
write("You Killed the Emojis!!",font=("Arial",30),align="center")
ht()
if not gameover:
screen.ontimer(play, 30)
bullets = []
#controls
def turnLeft():
ship.left(7)
def turnRight():
ship.right(7)
def go():
ship.fireEngine()
def fire():
ship.fireBullet()
ht()
screen.tracer(0);
screen.onkey(turnLeft, 'left')
screen.onkey(turnRight, 'right')
screen.onkey(go, 'up')
screen.onkey(fire, 'space')
screen.listen()
play()
You can use a threaded timer to prevent the method to be called everytime you click the button, and just two attributes in your SpaceShip class.
Everytime the method fireBullet is called, a check is made on the variable can_shoot. If it's true, the bullet is spawned like you did and then a timer runs (with a thread, for not blocking the main flow) that just put can_shoot to False, sleep for any amount of ms you want, and then put can_shoot to True and the method is callable again.
import time
import threading
def __init__(self):
# your stuff
self.wait_between_fire = 300 / 1000 # amount of ms / 1000 to convert in seconds
self.can_shoot = True
class TimerThread(threading.Thread):
def __init__(self, ref):
threading.Thread.__init__(self)
self.ref = ref
def run():
self.ref.can_shoot = False
time.sleep(ref.wait_between_fire)
self.ref.can_shoot = True
def set_timer(self):
TimerThread(self).start()
def fireBullet(self):
if self.can_shoot:
self.bullets.append(Bullet(self.screen, self.xcor(), self.ycor(), self.heading()))
self.set_timer()
We don't need to introduce time nor threading to solve this. We can use turtle's own timer events to control the rate of fire:
def fire():
screen.onkey(None, 'space')
ship.fireBullet()
screen.ontimer(lambda: screen.onkey(fire, 'space'), 250)
Here I've limited the rate of fire to 4 rounds per second. (250 / 1000 milliseconds.) Adjust as you see fit. Below is a rework of your program with this modification as well as other fixes and style tweaks:
from turtle import Screen, Turtle
from random import random, randint, randrange, choice
from math import radians, sin as sine, cos as cosine
class Bullet(Turtle):
MAX_DISTANCE = 500
DELTA = 20
RADIUS = 4
def __init__(self, position, heading):
super().__init__(shape="bullet")
self.hideturtle()
self.penup()
self.goto(position)
self.setheading(heading)
self.color('yellow')
self.showturtle()
self.distance = 0
def move(self):
self.distance += self.DELTA
self.forward(self.DELTA)
if self.done():
self.reset()
def getRadius(self):
''' collision detection helper method '''
return self.RADIUS
def blowUp(self):
''' method that makes something go off the screen '''
self.hideturtle()
def done(self):
return self.distance >= self.MAX_DISTANCE
class Asteroid(Turtle):
def __init__(self, dx, dy, position, size, emoji):
super().__init__()
self.hideturtle()
self.penup()
self.goto(position)
self.color('lightgrey')
emoji = choice(emojis)
# screen.addshape(emoji) # for StackOverflow debugging
self.shape(emoji)
self.showturtle()
self.size = size
self.dx = dx
self.dy = dy
def move(self):
x, y = self.position()
# if on edge of screen. go to opposite side
x = (self.dx + x - screenMinX) % (screenMaxX - screenMinX) + screenMinX
y = (self.dy + y - screenMinY) % (screenMaxY - screenMinY) + screenMinY
self.goto(x, y)
def blowUp(self):
''' method that makes something go off the screen '''
self.hideturtle()
def getRadius(self):
return self.size * 10 - 5
class SpaceShip(Turtle):
RADIUS = 10
def __init__(self, screen, dx, dy, x, y):
super().__init__(shape='turtle')
self.hideturtle()
self.penup()
self.color("white")
self.goto(x, y)
self.showturtle()
self.dx = dx
self.dy = dy
self.screen = screen
self.bullets = []
def move(self):
x, y = self.position()
x = (self.dx + x - screenMinX) % (screenMaxX - screenMinX) + screenMinX
y = (self.dy + y - screenMinY) % (screenMaxY - screenMinY) + screenMinY
self.goto(x, y)
def powPow(self, asteroids):
''' logic for collision '''
dasBullets = []
for bullet in self.bullets:
bullet.move()
hit = False
for asteroid in asteroids:
if intersect(asteroid, bullet): # counts every asteroid to see if it hits
asteroids.remove(asteroid)
asteroid.blowUp()
hit = True
if not bullet.done() and not hit:
dasBullets.append(bullet)
else:
bullet.blowUp()
self.bullets = dasBullets
def fireBullet(self):
bullet = Bullet(self.position(), self.heading())
self.bullets.append(bullet)
def fireEngine(self):
angle = self.heading() # how turtle moves
x = cosine(radians(angle))
y = sine(radians(angle))
self.dx = self.dx + x # how it rotates
self.dy = self.dy + y
self.dx = self.dx / speed1
self.dy = self.dy / speed1
def getRadius(self):
return self.RADIUS
def turnLeft(self):
self.left(7)
def turnRight(self):
self.right(7)
def intersect(object1, object2):
''' collision detection '''
return object1.distance(object2) <= object1.getRadius() + object2.getRadius()
def play():
# Tell all the elements of the game to move
ship.move()
gameover = False
for asteroid in asteroids:
r = randint(0, 1)
if r == 1:
asteroid.right(50)
else:
asteroid.left(20)
asteroid.move()
if intersect(ship, asteroid):
turtle.write("You Got Killed :(", font=("Verdana", 25), align="center")
gameover = True
ship.powPow(asteroids)
screen.update()
if not asteroids:
turtle.color('green')
turtle.write("You Killed the Emojis!!", font=("Arial", 30), align="center")
if not gameover:
screen.ontimer(play, 30)
# controls
def fire():
screen.onkey(None, 'space')
ship.fireBullet()
screen.ontimer(lambda: screen.onkey(fire, 'space'), 250)
# create a link to the object (creates the environment)
speed1 = 1.3
amountOfEmojis = 11
# establish important data for screen environment
screen = Screen()
screen.bgcolor("black")
# set a boundary for screen, if touches end, goes to the other side
screenMinX = -screen.window_width()/2
screenMinY = -screen.window_height()/2
screenMaxX = screen.window_width()/2
screenMaxY = screen.window_height()/2
screen.setworldcoordinates(screenMinX, screenMinY, screenMaxX, screenMaxY)
# adds object to screen
screen.register_shape("rock3", ((-20, -16), (-21, 0), (-20, 18), (0, 27), (17, 15), (25, 0), (16, -15), (0, -21)))
screen.register_shape("rock2", ((-15, -10), (-16, 0), (-13, 12), (0, 19), (12, 10), (20, 0), (12, -10), (0, -13)))
screen.register_shape("rock1", ((-10, -5), (-12, 0), (-8, 8), (0, 13), (8, 6), (14, 0), (12, 0), (8, -6), (0, -7)))
screen.register_shape("ship", ((-10, -10), (0, -5), (10, -10), (0, 10)))
screen.register_shape("bullet", ((-2, -4), (-2, 4), (2, 4), (2, -4)))
screen.tracer(0)
# turtle setup
turtle = Turtle()
turtle.hideturtle()
turtle.penup()
turtle.goto(0, screenMaxY - 50)
turtle.color('white')
turtle.write("Welcome to Emoji Run!", align="center", font=("Courier New", 26))
turtle.goto(0, screenMaxY - 70)
turtle.write("Use the arrow keys to move, and space to fire. The point of the game is to kill the emojis.", align="center", font=("Courier New", 13))
turtle.goto(0, 0)
turtle.color("red")
emojis = [
"Poop_Emoji_7b204f05-eec6-4496-91b1-351acc03d2c7_grande.png",
"1200px-Noto_Emoji_KitKat_263a.svg.png",
"annoyningface.png",
"Emoji_Icon_-_Sunglasses_cool_emoji_large.png"
]
emojis = ['rock1', 'rock2', 'rock3'] # for StackOverflow debugging purposes
# ship spawn exactly the middle everytime
ship = SpaceShip(screen, 0, 0, (screenMaxX - screenMinX)/2 + screenMinX, (screenMaxY - screenMinY)/2 + screenMinY)
# randomize where they spawn
asteroids = []
for k in range(amountOfEmojis):
dx, dy = random() * 6 - 3, random() * 6 - 3
x = randrange(10) * (screenMaxX - screenMinX) + screenMinX
y = random() * (screenMaxY - screenMinY) + screenMinY
asteroid = Asteroid(dx, dy, (x, y), randint(1, 3), emojis)
asteroids.append(asteroid)
screen.onkey(ship.turnLeft, 'Left')
screen.onkey(ship.turnRight, 'Right')
screen.onkey(ship.fireEngine, 'Up')
screen.onkey(fire, 'space')
screen.listen()
screen.update()
play()
screen.mainloop()
Something to consider is that turtles are global entities that don't get garbage collected. So, you might want to collect your spent bullets in a list to reuse, only creating new ones when you need them.
Related
I started playing a little with pygame and so far I'm not doing badly. I encountered a problem and managed to solve it. The solution is possible. It is not 100% correct. I want to implement an eat method when the head of the subject meets the food.
It is probably a relatively simple method when the rest of the value of X and Y are equal to the head of the snake being eaten.
For some reason I was not able to fully understand the overlap of pixels and I am not really correct in the method.
The problem at the moment is that there is no overlap between the pixels and "eating is not done".
BACKGROUND = pygame.image.load("background.jpg")
WIDTH, HEIGHT = BACKGROUND.get_width(), BACKGROUND.get_height()
pygame.font.init()
WIN = pygame.display.set_mode((WIDTH, HEIGHT))
def checkForEat(self):
head = self.body[-1]
x = self.food.getPos()[0]
y= self.food.getPos()[1]
# if abs(head[0] - x ) < 9 and abs(head[1] - y ) < 9: -- This is my temporary solution
if head[0] == x and head[1] == y:
self.food = Food()
self.eat()
I try not to add too much unnecessary code.
class Food:
def __init__(self):
self.color = (5, 5, 255)
self.pos = (random.randint(10,WIDTH-50),random.randint(10,HEIGHT-50))
def draw(self,win):
pygame.draw.circle(win,self.color, self.pos, 5)
def getPos(self):
return self.pos
class Snake:
START_POS = (85, 85)
def __init__(self):
self.food = Food()
self.block_size = 11
self.x , self.y = self.START_POS
self.body = self.create_body()
def create_body(self):
body = []
for i in range(self.length):
body.append((85,85+i*self.block_size))
return body
def draw(self,win):
WIN.blit(BACKGROUND, (0, 0))
self.food.draw(win)
for i in range(self.length):
pygame.draw.circle(win, (255, 0, 0), self.body[i], 5)
I'm not adding the rest of the program.
Just saying that apart from the problem I wrote above everything works fine.
Use pygame.Rect/pygame.Rect.colliderect to check if the bounding rectangle of the food overlaps with the head of the snake:
class Food:
def __init__(self):
self.color = (5, 5, 255)
self.pos = (random.randint(10,WIDTH-50),random.randint(10,HEIGHT-50))
def draw(self,win):
pygame.draw.circle(win,self.color, self.pos, 5)
def getPos(self):
return self.pos
def getRect(self):
return pygame.Rect(self.pos[0]-5, self.pos[1]-5, 10, 10)
class Snake:
START_POS = (85, 85)
def __init__(self):
self.food = Food()
self.block_size = 11
self.x , self.y = self.START_POS
self.body = self.create_body()
# [...]
def checkForEat(self):
head = self.body[-1]
head_rect = pygame.Rect(head[0]-5, head[1]-5, self.block_size, self.block_size)
food_rect = self.food.getRect()
if food_rect.colliderect(head_rect):
self.food = Food()
self.eat()
Also see How do I detect collision in pygame?.
Alternatively you can compute the Euclidean distance between the circle center of the circles and compare the distance to the sum of the radii:
class Snake:
# [...]
def checkForEat(self):
dx = self.food.getPos()[0] - self.body[-1][0]
dy = self.food.getPos()[1] - self.body[-1][1]
dist_center = math.hypot(dx, dy)
if dist_center <= 20:
self.food = Food()
self.eat()
I found a nice image of space that I'd like sitting in the background of this tiny game I'm working on and can't figure out what and where to write it. It needs to be placed behind all classes to make sure that it doesn't block the screen. I thought it might be in class Window, but I'm not sure. I am brand new to python so any help is much appreciated! This is the entire project so far.
import sys, logging, os, random, math, open_color, arcade
#check to make sure we are running the right version of Python
version = (3,7)
assert sys.version_info >= version, "This script requires at least Python {0}.{1}".format(version[0],version[1])
#turn on logging, in case we have to leave ourselves debugging messages
logging.basicConfig(format='[%(filename)s:%(lineno)d] %(message)s', level=logging.DEBUG)
logger = logging.getLogger(__name__)
SCREEN_WIDTH = 800
SCREEN_HEIGHT = 600
MARGIN = 30
SCREEN_TITLE = "Intergalactic slam"
NUM_ENEMIES = 5
STARTING_LOCATION = (400,100)
BULLET_DAMAGE = 10
ENEMY_HP = 10
HIT_SCORE = 10
KILL_SCORE = 100
PLAYER_HP = 100
class Bullet(arcade.Sprite):
def __init__(self, position, velocity, damage):
'''
initializes the bullet
Parameters: position: (x,y) tuple
velocity: (dx, dy) tuple
damage: int (or float)
'''
super().__init__("PNG/laserPink3.png", 0.5)
(self.center_x, self.center_y) = position
(self.dx, self.dy) = velocity
self.damage = damage
def update(self):
'''
Moves the bullet
'''
self.center_x += self.dx
self.center_y += self.dy
class Enemy_Bullet(arcade.Sprite):
def __init__(self, position, velocity, damage):
super().__init__("PNG/laserGreen1.png", 0.5)
(self.center_x, self.center_y) = position
(self.dx, self.dy) = velocity
self.damage = damage
def update(self):
self.center_x += self.dx
self.center_y += self.dy
class Player(arcade.Sprite):
def __init__(self):
super().__init__("PNG/shipYellow_manned.png", 0.5)
(self.center_x, self.center_y) = STARTING_LOCATION
self.hp = PLAYER_HP
class Enemy(arcade.Sprite):
def __init__(self, position):
'''
initializes an alien enemy
Parameter: position: (x,y) tuple
'''
super().__init__("PNG/shipGreen_manned.png", 0.5)
self.hp = ENEMY_HP
(self.center_x, self.center_y) = position
class Window(arcade.Window):
def __init__(self, width, height, title):
super().__init__(width, height, title)
file_path = os.path.dirname(os.path.abspath(__file__))
os.chdir(file_path)
self.set_mouse_visible(True)
arcade.set_background_color(open_color.black)
self.bullet_list = arcade.SpriteList()
self.enemy_list = arcade.SpriteList()
self.enemy_bullet_list = arcade.SpriteList()
self.player = Player()
self.score = 0
self.win = False
self.lose = False
def setup(self):
'''
Set up enemies
'''
for i in range(NUM_ENEMIES):
x = 120 * (i+1) + 40
y = 500
enemy = Enemy((x,y))
self.enemy_list.append(enemy)
def update(self, delta_time):
self.bullet_list.update()
self.enemy_bullet_list.update()
if (not (self.win or self.lose)):
for e in self.enemy_list:
for b in self.bullet_list:
if (abs(b.center_x - e.center_x) <= e.width / 2 and abs(b.center_y - e.center_y) <= e.height / 2):
self.score += HIT_SCORE
e.hp -= b.damage
b.kill()
if (e.hp <= 0):
e.kill()
self.score += KILL_SCORE
if (len(self.enemy_list) == 0):
self.win = True
if (random.randint(1, 75) == 1):
self.enemy_bullet_list.append(Enemy_Bullet((e.center_x, e.center_y - 15), (0, -10), BULLET_DAMAGE))
for b in self.enemy_bullet_list:
if (abs(b.center_x - self.player.center_x) <= self.player.width / 2 and abs(b.center_y - self.player.center_y) <= self.player.height / 2):
self.player.hp -= b.damage
b.kill()
if (self.player.hp <= 0):
self.lose = True
def on_draw(self):
arcade.start_render()
arcade.draw_text(str(self.score), 20, SCREEN_HEIGHT - 40, open_color.white, 16)
arcade.draw_text("HP: {}".format(self.player.hp), 20, 40, open_color.white, 16)
if (self.player.hp > 0):
self.player.draw()
self.bullet_list.draw()
self.enemy_bullet_list.draw()
self.enemy_list.draw()
if (self.lose):
self.draw_game_loss()
elif (self.win):
self.draw_game_won()
def draw_game_loss(self):
arcade.draw_text(str("LOSER!"), SCREEN_WIDTH / 2 - 90, SCREEN_HEIGHT / 2 - 10, open_color.white, 30)
def draw_game_won(self):
arcade.draw_text(str("WINNER!"), SCREEN_WIDTH / 2 - 90, SCREEN_HEIGHT / 2 - 10, open_color.white, 30)
def on_mouse_motion(self, x, y, dx, dy):
'''
The player moves left and right with the mouse
'''
self.player.center_x = x
def on_mouse_press(self, x, y, button, modifiers):
if button == arcade.MOUSE_BUTTON_LEFT:
x = self.player.center_x
y = self.player.center_y + 15
bullet = Bullet((x,y),(0,10),BULLET_DAMAGE)
self.bullet_list.append(bullet)
def main():
window = Window(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_TITLE)
window.setup()
arcade.run()
if __name__ == "__main__":
main()
One way to do it would be to load the .jpg or .png as a texture, and draw that texture each frame, as big as the screen is (or bigger!).
I haven't tested this, but as an example, loading the texture could be done in Window.__init__, like so (reference):
self.background = arcade.load_texture('PNG/background.png')
And then in on_draw, just after you call start_render, you would draw it (reference), passing the required center coordinates, as well as width and height:
self.background.draw(SCREEN_WIDTH/2, SCREEN_HEIGHT/2, SCREEN_WIDTH, SCREEN_HEIGHT)
The reason it needs to be the first thing is because everything is drawn back-to-front, like you would do in a painting.
If the image is not the exact same size as your screen/window, your background will probably be stretched/squished. If that's not what you want, the easiest fix would be to change the image so that it's the right size.
Yes, you should be able to add it to class window...
You could do something like this to add it:
def __init__(self, width, height, title):
super().__init__(width, height, title)
file_path = os.path.dirname(os.path.abspath(__file__))
os.chdir(file_path)
self.set_mouse_visible(True)
arcade.set_background_color(open_color.black)
self.bullet_list = arcade.SpriteList()
self.enemy_list = arcade.SpriteList()
self.enemy_bullet_list = arcade.SpriteList()
self.player = Player()
self.score = 0
self.win = False
self.lose = False
self.background = None
def setup(self):
'''
Set up enemies
'''
self.background = arcade.load_texture("images/background.jpg")
for i in range(NUM_ENEMIES):
x = 120 * (i+1) + 40
y = 500
enemy = Enemy((x,y))
self.enemy_list.append(enemy)
Below is the code I am trying to get working, i currently have it creating the sprites although once the second sprite is created the movement for the first is stopped.
Say there are 2 sprites both of them should be moving individually, completely random from each other.
The code creates a new sprite every 3 seconds(for testing purposes once the code is working it will be set to 10 seconds)
class enemymove(object):
def create():
global enemy, radiusenemy, xenemy, yenemy
amount = 0
enemy = list()
xenemy = list()
yenemy = list()
enemypositionx = list()
enemypositiony = list()
lastop = len(enemy)
enemy.append(amount)
xenemy.append(amount)
yenemy.append(amount)
enemypositionx.append(amount)
enemypositiony.append(amount)
amount = amount + 1
radiusenemy = 12.5
enemypositionx[lastop] = random.uniform(12.5, resX-12.5)
enemypositiony[lastop] = random.uniform(12.5, resY-12.5)
print(lastop)
enemy[lastop] = canvas.create_oval((enemypositionx[lastop]) + radiusenemy ,(enemypositiony[lastop]) - radiusenemy ,(enemypositionx[lastop]) - radiusenemy ,(enemypositiony[lastop]) + radiusenemy, fill="black", outline="black")
xenemy[lastop] = (canvas.coords(enemy[lastop])[2]) - 12.5
yenemy[lastop] = (canvas.coords(enemy[lastop])[3]) - 12.5
Thread(target = spawntime.timer).start()
enemymove.movement(lastop);
def movement(lastop):
global timer
timer = random.randint(150,3000)
count = random.randint(1, 4)
print(count)
if count == 1:
enemymove.up(lastop);
if count == 2:
enemymove.downward(lastop);
if count == 3:
enemymove.rightran(lastop);
if count == 4:
enemymove.leftran(lastop);
def up(lastop):
global xenemy, yenemy
print ("forward")
yenemy[lastop] = (canvas.coords(enemy[lastop])[1])
canvas.coords(enemy[lastop], xenemy[lastop] + radiusenemy, yenemy[lastop] + radiusenemy, xenemy[lastop] - radiusenemy, yenemy[lastop] - radiusenemy)
print(yenemy)
print(xenemy)
canvas.after(timer, enemymove.movement, lastop)
def downward(lastop):
global xenemy, yenemy
print("back")
yenemy[lastop] = (canvas.coords(enemy[lastop])[3])
canvas.coords(enemy[lastop], xenemy[lastop] - radiusenemy, yenemy[lastop] + radiusenemy, xenemy[lastop] + radiusenemy, yenemy[lastop] - radiusenemy)
print(yenemy)
print(xenemy)
canvas.after(timer, enemymove.movement, lastop)
def rightran(lastop):
global xenemy, yenemy
print("right")
xenemy[lastop] = (canvas.coords(enemy[lastop])[2])
canvas.coords(enemy[lastop], xenemy[lastop] - radiusenemy, yenemy[lastop] - radiusenemy, xenemy[lastop] + radiusenemy, yenemy[lastop] + radiusenemy)
print(yenemy)
print(xenemy)
canvas.after(timer, enemymove.movement, lastop)
def leftran(lastop):
global xenemy, yenemy
print("left")
xenemy[lastop] = (canvas.coords(enemy[lastop])[0])
canvas.coords(enemy[lastop], xenemy[lastop] - radiusenemy, yenemy[lastop] - radiusenemy, xenemy[lastop] + radiusenemy, yenemy[lastop] + radiusenemy)
print(yenemy)
print(xenemy)
canvas.after(timer, enemymove.movement, lastop)
class spawntime():
def timer():
global timeset
timeset = 3
spawntime.calculation()
def calculation():
global timeset
print ('The count is: ', timeset)
if timeset <= 0:
enemymove.create()
else:
timeset -= 1
canvas.after(1000, spawntime.calculation)
#runs the main code
def main():
global root, canvas
root.title("")
canvas = Canvas(root, width= resX, height=resY, bg = "white")
canvas.pack()
Thread(target = spawntime.timer).start()
root.mainloop()
main()
I'm reasonably new to appending, so making multiple different appended sprites move all together is out of my range, and so I am unsure of how to get this to work.
I don't understand your code so I create own version. Now every enemy moves after random time. After random time I add new enemy
I keep enemies on list but I don't need this list.
import random
import tkinter as tk
# --- constants --- # UPPERCASE name
RES_X = 800
RES_Y = 600
# --- classes --- # CamelCase name
class Enemies(object):
def __init__(self, canvas):
# access to canvas
self.canvas = canvas
# started amount of enemies
self.amount = 5
# list for all enemies
self.enemies = list()
# create enemies
for _ in range(self.amount):
self.create_one_enemy()
def create_one_enemy(self):
radius = 12.5 # random
x = random.uniform(radius, RES_X-radius)
y = random.uniform(radius, RES_Y-radius)
oval = self.canvas.create_oval(x-radius, y-radius, x+radius, y+radius, fill="black", outline="black")
# one enemy
enemy = [x, y, radius, oval]
# apped to list - but I don't need this list
self.enemies.append(enemy)
# move this enemy after random time
random_time = random.randint(150, 3000)
root.after(random_time, self.move_one_enemy, enemy)
def move_one_enemy(self, enemy):
#print('moving:', enemy)
# get old values
x, y, radius, oval = enemy
direction = random.randint(1,4)
if direction == 1: # up
y -= radius
elif direction == 2: # down
y += radius
elif direction == 3: # left
x -= radius
elif direction == 4: # right
x += radius
self.canvas.coords(oval, x-radius, y-radius, x+radius, y+radius)
# remember new values
enemy[0] = x
enemy[1] = y
# move this enemy after random time
random_time = random.randint(150, 3000)
root.after(random_time, self.move_one_enemy, enemy)
# --- functions --- # lower_case name
def add_new_enemy():
enemies.create_one_enemy()
# add next enemy after random time
timer = random.randint(150, 3000)
root.after(random_time, add_new_enemy)
# --- main ---
root = tk.Tk()
root.title("")
canvas = tk.Canvas(root, width=RES_X, height=RES_Y, bg="white")
canvas.pack()
# create enemies and move it using `root.after`
enemies = Enemies(canvas)
# add new enemy after random time
random_time = random.randint(150, 3000)
root.after(random_time, add_new_enemy)
root.mainloop()
EDIT: but rather I would create class Enemy for single enemy and then list enemies to keep all Enemy instances.
import random
import tkinter as tk
# --- constants --- # UPPERCASE name
RES_X = 800
RES_Y = 600
# --- classes --- # CamelCase name
class Enemy(object):
'''single enemy'''
def __init__(self, canvas):
# access to canvas
self.canvas = canvas
self.radius = 12.5 # random
self.color = random.choice( ('black', 'red', 'green', 'blue', 'yellow') )
self.x = random.uniform(self.radius, RES_X-self.radius)
self.y = random.uniform(self.radius, RES_Y-self.radius)
self.x1 = self.x-self.radius
self.y1 = self.y-self.radius
self.x2 = self.x+self.radius
self.y2 = self.y+self.radius
self.oval = self.canvas.create_oval(self.x1, self.y1, self.x2, self.y2, fill=self.color, outline=self.color)
self.moving = True
self.start()
def start(self):
'''start moving'''
self.moving = True
# move this enemy after random time
random_time = random.randint(150, 3000)
root.after(random_time, self.move)
def stop(self):
'''stop moving'''
self.moving = False
def move(self):
if self.moving: # to stop root.after
direction = random.randint(1,4)
if direction == 1: # up
self.y -= self.radius
self.y1 -= self.radius
self.y2 -= self.radius
elif direction == 2: # down
self.y += self.radius
self.y1 += self.radius
self.y2 += self.radius
elif direction == 3: # left
self.x -= self.radius
self.x1 -= self.radius
self.x2 -= self.radius
elif direction == 4: # right
self.x += self.radius
self.x1 += self.radius
self.x2 += self.radius
self.canvas.coords(self.oval, self.x1, self.y1, self.x2, self.y2)
# move this enemy after random time
random_time = random.randint(150, 3000)
root.after(random_time, self.move)
# --- functions --- # lower_case name
def add_new_enemy():
enemies.append(Enemy(canvas))
# add next enemy after random time
timer = random.randint(150, 3000)
root.after(random_time, add_new_enemy)
# --- main ---
root = tk.Tk()
root.title("")
canvas = tk.Canvas(root, width=RES_X, height=RES_Y, bg="white")
canvas.pack()
# 5 enemies at the beginning
enemies = list()
for _ in range(5):
enemies.append(Enemy(canvas))
# add new enemy after random time
random_time = random.randint(150, 3000)
root.after(random_time, add_new_enemy)
root.mainloop()
And now you can use list to stop/start enemies
for one_enemy in enemies:
one_enemy.stop()
or check some information
for one_enemy in enemies:
print("x:", one_enemy.x)
print("y:", one_enemy.y)
btw: and then you can create EnemiesGroup class
EDIT: EnemiesGroup and buttons to control group
import random
import tkinter as tk
# --- constants --- # UPPERCASE name
RES_X = 800
RES_Y = 600
# --- classes --- # CamelCase name
class Enemy(object):
'''single enemy'''
def __init__(self, canvas):
# access to canvas
self.canvas = canvas
self.radius = 12.5 # random
self.color = random.choice( ('black', 'red', 'green', 'blue', 'yellow') )
self.x = random.uniform(self.radius, RES_X-self.radius)
self.y = random.uniform(self.radius, RES_Y-self.radius)
self.x1 = self.x-self.radius
self.y1 = self.y-self.radius
self.x2 = self.x+self.radius
self.y2 = self.y+self.radius
self.oval = self.canvas.create_oval(self.x1, self.y1, self.x2, self.y2, fill=self.color, outline=self.color)
self.moving = True
self.start()
def start(self):
'''start moving'''
self.moving = True
# move this enemy after random time
random_time = random.randint(150, 3000)
root.after(random_time, self.move)
def stop(self):
'''stop moving'''
self.moving = False
def move(self):
if self.moving: # to stop root.after
direction = random.randint(1,4)
if direction == 1: # up
self.y -= self.radius
self.y1 -= self.radius
self.y2 -= self.radius
elif direction == 2: # down
self.y += self.radius
self.y1 += self.radius
self.y2 += self.radius
elif direction == 3: # left
self.x -= self.radius
self.x1 -= self.radius
self.x2 -= self.radius
elif direction == 4: # right
self.x += self.radius
self.x1 += self.radius
self.x2 += self.radius
self.canvas.coords(self.oval, self.x1, self.y1, self.x2, self.y2)
# move this enemy after random time
random_time = random.randint(150, 3000)
root.after(random_time, self.move)
class EnemiesGroup(object):
def __init__(self, canvas):
self.canvas = canvas
self.enemies = list()
self.moving = True
def add_new_enemy(self):
# can be only 5 enemies
if len(self.enemies) < 5:
e = Enemy(self.canvas)
# stop new enemy if all enemies are stoped
e.moving = self.moving
self.enemies.append(e)
else:
print("You have 5 enemies - I can't add more.")
def stop_all_enemies(self):
for e in self.enemies:
e.stop()
# all enemies are stoped
self.moving = False
def start_all_enemies(self):
for e in self.enemies:
e.start()
# all enemies are moving
self.moving = True
# --- functions --- # lower_case name
def add_new_enemy():
enemies_group.add_new_enemy()
# add next enemy after random time
timer = random.randint(150, 3000)
root.after(random_time, add_new_enemy)
# --- main ---
root = tk.Tk()
root.title("")
canvas = tk.Canvas(root, width=RES_X, height=RES_Y, bg="white")
canvas.pack()
# enemies
enemies_group = EnemiesGroup(canvas)
for _ in range(5):
enemies_group.add_new_enemy()
# add new enemy after random time
random_time = random.randint(150, 3000)
root.after(random_time, add_new_enemy)
# buttons to control all enemies
button_stop = tk.Button(root, text='STOP', command=enemies_group.stop_all_enemies)
button_stop.pack()
button_start = tk.Button(root, text='START', command=enemies_group.start_all_enemies)
button_start.pack()
button_add = tk.Button(root, text='ADD NEW ENEMY', command=enemies_group.add_new_enemy)
button_add.pack()
root.mainloop()
EDIT: removing enemy by clicking oval.
In add_new_enemy I bind to oval event <Button-1> and function clicked (with enemy object).
Function clicked removes oval from canvas and removes enemy from enemies group.
class EnemiesGroup(object):
# ... other functions ...
def clicked(self, event, enemy):
print('clicked:', enemy),
# remove oval from canvas
self.canvas.delete(enemy.oval)
# remove enemy from list
self.enemies.remove(enemy)
# create new enemy after 10s
root.after(10000, self.add_new_enemy)
def add_new_enemy(self):
# can be only 5 enemies
if len(self.enemies) < 5:
print('create new enemy')
e = Enemy(self.canvas)
# stop new enemy if all enemies are stoped
e.moving = self.moving
# bind mouse button to enemy
self.canvas.tag_bind(e.oval, '<Button-1>', lambda event:self.clicked(event, e))
self.enemies.append(e)
else:
print("You have 5 enemies - I can't add more.")
# ... other functions ...
This question already has answers here:
Why it doesn't spin in a circle? And how to fix it?
(1 answer)
Ship moves up and left faster than down and right when rotating in pygame
(1 answer)
Closed 2 years ago.
This question is related to
My code is below. You can use any small image for my images.
import sys, os, pygame, itertools
from math import sin,cos,pi, radians
from pygame.locals import *
os.environ['SDL_VIDEO_WINDOW_POS'] = "%d,%d" % (50,50) #Set window position
pygame.init()
clock = pygame.time.Clock()
FPS = 1000
SCREENW = 800 #screen width
SCREENH = 740 #screen height
BLACK = (0, 0, 0)
BLUE = (0, 0, 255)
ORANGE = (128, 100, 30)
FONT1= "Cookie-Regular.ttf"
SCREEN = pygame.display.set_mode((SCREENW, SCREENH), 0, 32) #display screen
clock = pygame.time.Clock()
#-------------------------------------------------------------------------------
def maketext(msg,fontsize, colour = ORANGE, font = FONT1):
mafont = pygame.font.Font(font, fontsize)
matext = mafont.render(msg, True, colour)
matext = matext.convert_alpha()
return matext
#-------------------------------------------------------------------------------
def print_info():
""""""
textcos = maketext(str(round(obj.rect.x, 2)) + " " + str(round(obj.rect.y, 2)), 30)
SCREEN.blit(textcos, (obj.rect.x, obj.rect.y + 30))
#-------------------------------------------------------------------------------
class object_factory(pygame.sprite.Sprite):
def __init__(self, imagelist, xpos, ypos, speedx = 0, speedy = 0, value = 0):
"""Constructor"""
pygame.sprite.Sprite.__init__(self)
self.name = ""
self.frame = 0
self.imagelist = imagelist
self.image = imagelist[self.frame]
self.mask = pygame.mask.from_surface(self.image) # pixelmask
self.rect = self.image.get_rect()
self.rect.x = xpos
self.rect.y = ypos
#self.speedx = speedx
#self.speedy = speedy
self.timer = 0
self.timerlimit = 10
#----------------------------------------------------------------------
#def move(self): # wallsprites, Herosprite, looptime
#self.rect.x += self.speedx
#self.rect.y += self.speedy
#----------------------------------------------------------------------
def update(self):
""""""
self.image = self.imagelist[self.frame]
if self.timer >= self.timerlimit:
self.frame += 1
if self.frame >= len(self.imagelist):
self.frame = 0
self.timer = 0
self.timer += 1
plat = pygame.image.load("plt0.png").convert_alpha()
star = pygame.image.load("gemp0.png").convert_alpha()
#box = pygame.image.load("crateB.png").convert_alpha()
platforms = pygame.sprite.Group()
boxes = pygame.sprite.Group()
rotcenx = SCREENW/2
rotceny = SCREENH/2
radius = 200
angle = radians(90) #pi/4 # starting angle 45 degrees
omega = radians(5) #Angular velocity
m = rotcenx + radius * cos(angle) #Starting position x
n = rotceny - radius * sin(angle) #Starting position y
for _ in itertools.repeat(None, 1):
madyax = SCREENW/2
madyay = SCREENH/2
araya = 200
konaya = radians(180) #pi/4 # starting angle 45 degrees
konika_pravegaya = radians(5) #Angular velocity
a = madyax + (araya * cos(konaya)) #Starting position x
b = madyay - (araya * sin(konaya)) #Startinh position y
plat = object_factory([plat], a, b)
plat.araya = araya
plat.konaya = konaya
plat.kp = konika_pravegaya
platforms.add(plat)
while True:
ms = clock.tick(FPS) # milliseconds passed since last frame
#looptime = milliseconds / 1000.0 # seconds passed since last frame
SCREEN.fill((BLACK))
pygame.draw.circle(SCREEN, BLUE, (SCREENW / 2, SCREENH / 2), 5)
##-----------------------------------------------------------
SCREEN.blit(star, (m, n)) # Draw current x,y
angle = angle + omega # New angle, we add angular velocity
m = m + radius * omega * cos(angle + pi / 2) # New x
n = n - radius * omega * sin(angle + pi / 2) # New y
##-----------------------------------------------------------
# show object anchored to center of rotation
pygame.draw.line(SCREEN, ORANGE, (rotcenx, rotceny), (m, n))
text = maketext(str(radius), 30)
SCREEN.blit(text, (m, n - 40))
text = maketext((str(round(m, 2)) + " " + str(round(n, 2))), 30)
SCREEN.blit(text, (m, n + 40)) # Draw current x,y
##------------------------------------------------------------------
for plat in platforms:
plat.konaya = plat.konaya + plat.kp
plat.rect.x = plat.rect.x + plat.araya * plat.kp * cos(plat.konaya + pi / 2)
plat.rect.y = plat.rect.y - plat.araya * plat.kp * sin(plat.konaya + pi / 2)
##------------------------------------------------------------------------
pygame.draw.line(SCREEN, ORANGE, (madyax, madyay), (plat.rect.x, plat.rect.y))
platforms.update()
platforms.draw(SCREEN)
pygame.event.pump()
keys = pygame.key.get_pressed()
for event in pygame.event.get():
if event.type == QUIT or (event.type == KEYDOWN and event.key == K_ESCAPE):
pygame.quit()
sys.exit()
pygame.display.update()
pygame.time.wait(100)
Why does the code work when used outside a class and NOT when in? I simply can't find what I have done wrong.
Please don't ask me to read any Google documents or search on the Internet as I am posting after doing so and NOT finding an answer to my question. I am NOT an expert in math and would only like to know a solution to this problem. Please help.
Link to video is below
http://youtu.be/0oRDX246aj8
I'm using openGL with Pyglet which is a python package. I have to use this language and this package, it is for an assignment. I have a basic Brickbreaker style game that is basically a keep it up game.
I create a ball and a paddle.
I separately create a bounding box class that will be used to create the hit boxes for each object.
class BoundBox:
def __init__ (self, width, height, pos):
self.width = width
self.height = height
self.pos = pos
Then I create the boxes themselves
paddleBox = BoundBox(200, 20, [0,0])
ballBox = BoundBox(40, 40, [236, 236])
In the update function which is running # pyglet.clock.schedule_interval(update,1/100.0) I call the checkcollide() function which checks if there was a collision:
def checkForCollide():
global collides
if overlap(ballBox, paddleBox):
vel = 1.05
ballVel[0] = ballVel[0]*vel #Ball speeds up when collide happens
ballVel[1] = ballVel[1]*vel
ballVel[1] = -ballVel[1] #Change direction on collision
ballPos[1] = -ballPos[1]
collides += 1 #counts how many collides happen
The overlap function is returning a boolean if there's an overlap in hit boxes:
def overlap(box1, box2):
return (box1.pos[0] <= box2.width + box2.pos[0]) and(box1.width + box1.pos[0] >= box2.pos[0]) and(box1.pos[1] <= box2.height + box2.pos[1]) and(box1.height + box1.pos[1] >= box2.pos[1])
pos[0] is the minimum x
width is the maximum x
pos[1] is the minimum y
height is the maximum y
When I run the game and the ball hits the paddle it flickers about 15 times and increments the collides counter every time it detects a hit. Collides then prints in the console. Why does this flicker happen? How do I stop it?
Here is the program's full code (you must have pyglet installed to run it):
import sys, time, math
from pyglet.gl import *
from euclid import *
from pyglet.window import key
from pyglet.clock import *
window = pyglet.window.Window(512,512)
quadric = gluNewQuadric()
ballPos = Vector2(256,256)
ballVel = Vector2(200,145)
x1 = 0
bar = pyglet.graphics.vertex_list(4, ('v2f', [0,0, 0,20, 200,0, 200,20]))
startTime = time.clock()
collides = 0
#pos is minx, miny
class BoundBox:
def __init__ (self, width, height, pos):
self.width = width
self.height = height
self.pos = pos
def overlap(box1, box2):
return (box1.pos[0] <= box2.width + box2.pos[0]) and(box1.width + box1.pos[0] >= box2.pos[0]) and(box1.pos[1] <= box2.height + box2.pos[1]) and(box1.height + box1.pos[1] >= box2.pos[1])
paddleBox = BoundBox(200, 20, [0,0])
ballBox = BoundBox(40, 40, [236, 236])
#window.event
def on_draw():
glClear(GL_COLOR_BUFFER_BIT)
glPushMatrix()
glPushMatrix()
glColor3f(1,1,1)
glTranslatef(x1, 0, 0)
bar.draw(GL_TRIANGLE_STRIP)
glPopMatrix()
glTranslatef(ballPos[0], ballPos[1], 0)
glColor3f(1,0,0)
gluDisk(quadric, 0, 20, 32, 1)
glPopMatrix()
#window.event
def on_key_press(symbol, modifiers):
global x1
dist = 30
if symbol == key.RIGHT:
#print "right"
x1 += dist
elif symbol == key.LEFT:
#print "left"
x1 -= dist
def checkForBounce():
if ballPos[0] > 512.0:
ballVel[0] = -ballVel[0]
ballPos[0] = 512.0 - (ballPos[0] - 512.0)
elif ballPos[0] < 0.0:
ballVel[0] = -ballVel[0]
ballPos[0] = -ballPos[0]
if ballPos[1] > 512.0:
ballVel[1] = -ballVel[1]
ballPos[1] = 512.0 - (ballPos[1] - 512.0)
elif ballPos[1] < -100.0:
gameOver()
def gameOver():
global collides
'''global startTime
elapsed = (time.time() - startTime)
score = elapsed * .000000001
finalscore = '%.1f' % round(score, 1)'''
gostr = "GAME OVER"
print gostr
str = "Your score = "
print str
print collides
pyglet.app.exit()
def checkForCollide():
global collides
if overlap(ballBox, paddleBox):
vel = 1.05
ballVel[0] = ballVel[0]*vel #Ball speeds up when collide happens
ballVel[1] = ballVel[1]*vel
ballVel[1] = -ballVel[1] #Change direction on collision
ballPos[1] = -ballPos[1]
collides += 1 #counts how many collides happen
print collides
#glscale(0.5, 1, 1)
def update(dt):
global ballPos, ballVel, ballBox, x1, paddleBox
ballBox = BoundBox(40, 40, [ballPos[0], ballPos[1]])
paddleBox = BoundBox(200, 20, [x1,0])
#print paddleBox.pos
#print ballBox.pos
ballPos += ballVel * dt
checkForBounce()
checkForCollide()
pyglet.clock.schedule_interval(update,1/100.0)
pyglet.app.run()
I don't think you wanted to invert the position here:
def checkForCollide():
global collides
if overlap(ballBox, paddleBox):
vel = 1.05
ballVel[0] = ballVel[0]*vel #Ball speeds up when collide happens
ballVel[1] = ballVel[1]*vel
ballVel[1] = -ballVel[1] #Change direction on collision
ballPos[1] = -ballPos[1]
collides += 1 #counts how many collides happen
What were you trying to do with this line?
ballPos[1] = -ballPos[1]
I suspect that is why you are flickering.