Related
I am trying to build a Breakout game for python tkinter with different levels. I don't quite understand the self and __init__ functions in this code.
Is there a way to create the game without those functions or replacing them with simpler functions if it's possible? Also, I don't quite understand the + self.radius parts in the code as well.
import tkinter as tk
def new_window():
root1 = tk.Tk()
root1.title('Jeu')
game = Game(root1)
class GameObject(object):
def __init__(self, canvas, item):
self.canvas = canvas
self.item = item
def get_position(self):
return self.canvas.coords(self.item)
def move(self, x, y):
self.canvas.move(self.item, x, y)
def delete(self):
self.canvas.delete(self.item)
class Ball(GameObject):
def __init__(self, canvas, x, y):
self.radius = 10
self.direction = [1, -1]
# increase the below value to increase the speed of ball
self.speed = 5
item = canvas.create_oval(x - self.radius, y - self.radius,
x + self.radius, y + self.radius,
fill='white')
super(Ball, self).__init__(canvas, item)
def update(self):
coords = self.get_position()
width = self.canvas.winfo_width()
if coords[0] <= 0 or coords[2] >= width:
self.direction[0] *= -1
if coords[1] <= 0:
self.direction[1] *= -1
x = self.direction[0] * self.speed
y = self.direction[1] * self.speed
self.move(x, y)
def collide(self, game_objects):
coords = self.get_position()
x = (coords[0] + coords[2]) * 0.5
if len(game_objects) > 1:
self.direction[1] *= -1
elif len(game_objects) == 1:
game_object = game_objects[0]
coords = game_object.get_position()
if x > coords[2]:
self.direction[0] = 1
elif x < coords[0]:
self.direction[0] = -1
else:
self.direction[1] *= -1
for game_object in game_objects:
if isinstance(game_object, Brick):
game_object.hit()
class Paddle(GameObject):
def __init__(self, canvas, x, y):
self.width = 80
self.height = 10
self.ball = None
item = canvas.create_rectangle(x - self.width / 2,
y - self.height / 2,
x + self.width / 2,
y + self.height / 2,
fill='#FFB643')
super(Paddle, self).__init__(canvas, item)
def set_ball(self, ball):
self.ball = ball
def move(self, offset):
coords = self.get_position()
width = self.canvas.winfo_width()
if coords[0] + offset >= 0 and coords[2] + offset <= width:
super(Paddle, self).move(offset, 0)
if self.ball is not None:
self.ball.move(offset, 0)
class Brick(GameObject):
COLORS = {1: '#4535AA', 2: '#ED639E', 3: '#8FE1A2'}
def __init__(self, canvas, x, y, hits):
self.width = 75
self.height = 20
self.hits = hits
color = Brick.COLORS[hits]
item = canvas.create_rectangle(x - self.width / 2,
y - self.height / 2,
x + self.width / 2,
y + self.height / 2,
fill=color, tags='brick')
super(Brick, self).__init__(canvas, item)
def hit(self):
self.hits -= 1
if self.hits == 0:
self.delete()
else:
self.canvas.itemconfig(self.item,
fill=Brick.COLORS[self.hits])
class Game(tk.Frame):
def __init__(self, master):
super(Game, self).__init__(master)
self.lives = 3
self.width = 610
self.height = 400
self.canvas = tk.Canvas(self, bg='#D6D1F5',
width=self.width,
height=self.height, )
self.canvas.pack()
self.pack()
self.items = {}
self.ball = None
self.paddle = Paddle(self.canvas, self.width / 2, 326)
self.items[self.paddle.item] = self.paddle
# adding brick with different hit capacities - 3,2 and 1
for x in range(5, self.width - 5, 75):
self.add_brick(x + 37.5, 50, 3)
self.add_brick(x + 37.5, 70, 2)
self.add_brick(x + 37.5, 90, 1)
self.hud = None
self.setup_game()
self.canvas.focus_set()
self.canvas.bind('<Left>',
lambda _: self.paddle.move(-10))
self.canvas.bind('<Right>',
lambda _: self.paddle.move(10))
def setup_game(self):
self.add_ball()
self.update_lives_text()
self.text = self.draw_text(300, 200,
'Press Space to start')
self.canvas.bind('<space>', lambda _: self.start_game())
def add_ball(self):
if self.ball is not None:
self.ball.delete()
paddle_coords = self.paddle.get_position()
x = (paddle_coords[0] + paddle_coords[2]) * 0.5
self.ball = Ball(self.canvas, x, 310)
self.paddle.set_ball(self.ball)
def add_brick(self, x, y, hits):
brick = Brick(self.canvas, x, y, hits)
self.items[brick.item] = brick
def draw_text(self, x, y, text, size='40'):
font = ('Forte', size)
return self.canvas.create_text(x, y, text=text,
font=font)
def update_lives_text(self):
text = 'Lives: %s' % self.lives
if self.hud is None:
self.hud = self.draw_text(50, 20, text, 15)
else:
self.canvas.itemconfig(self.hud, text=text)
def start_game(self):
self.canvas.unbind('<space>')
self.canvas.delete(self.text)
self.paddle.ball = None
self.game_loop()
def game_loop(self):
self.check_collisions()
num_bricks = len(self.canvas.find_withtag('brick'))
if num_bricks == 0:
self.ball.speed = None
self.draw_text(300, 200, 'You win! You the Breaker of Bricks.')
elif self.ball.get_position()[3] >= self.height:
self.ball.speed = None
self.lives -= 1
if self.lives < 0:
self.draw_text(300, 200, 'You Lose! Game Over!')
else:
self.after(1000, self.setup_game)
else:
self.ball.update()
self.after(50, self.game_loop)
def check_collisions(self):
ball_coords = self.ball.get_position()
items = self.canvas.find_overlapping(*ball_coords)
objects = [self.items[x] for x in items if x in self.items]
self.ball.collide(objects)
game.mainloop()
root = tk.Tk()
root.title('Jeu')
game = Game(root)
btn1= tk.Button(root, text='Click me', bd= '5',command=new_window)
Is there a way to create the game without those functions or replacing them with simpler functions if it's possible?
As a proof of concept below a much simpler code of the game for beginners rewritten to get rid of classes as an example that it is possible to write the game without them. You can compare the rewritten code with the original code (link is given in a comment at the beginning of code) to see how it can be done and then rewrite yourself a more complex code:
# https://codingshiksha.com/python/python-3-tkinter-2d-brick-breaker-breakout-game-in-gui-desktop-app-full-project-for-beginners/
from tkinter import Tk, Canvas
import random
import time
tk = Tk()
tk.title("Game")
tk.resizable(0, 0)
tk.wm_attributes("-topmost", 1)
canvas_height = 400
canvas_width = 500
canvas = Canvas(tk, width=canvas_width, height=canvas_height, bd=0, highlightthickness=0)
canvas.pack()
tk.update()
ball_id = canvas.create_oval(10, 10, 25, 25, fill='red')
canvas.move(ball_id, 245, 100)
starts = [-3, -2, -1, 1, 2, 3]
random.shuffle(starts)
ball_x = starts[0]
ball_y = -3
paddle_id = canvas.create_rectangle(0, 0, 100, 10, fill='blue')
canvas.move(paddle_id, 200, 300)
paddle_x = 0
def draw_ball():
global ball_x, ball_y
canvas.move(ball_id, ball_x, ball_y)
pos = canvas.coords(ball_id)
if pos[1] <= 0:
ball_y = 3
if pos[3] >= canvas_height:
ball_y = -3
if hit_paddle(pos) == True:
ball_y = -3
if pos[0] <= 0:
ball_x = 3
if pos[2] >= canvas_width:
ball_x = -3
def hit_paddle(pos):
paddle_pos = canvas.coords(paddle_id)
if pos[2] >= paddle_pos[0] and pos[0] <= paddle_pos[2]:
if pos[3] >= paddle_pos[1] and pos[3] <= paddle_pos[3]:
return True
return False
def turn_left(evt):
global paddle_x
paddle_x = -2
def turn_right(evt):
global paddle_x
paddle_x = 2
def draw_paddle():
global paddle_x
canvas.move(paddle_id, paddle_x, 0)
pos = canvas.coords(paddle_id)
if pos[0] <= 0:
paddle_x = 0
elif pos[2] >= canvas_width:
paddle_x = 0
canvas.bind_all('<KeyPress-Left>' , turn_left)
canvas.bind_all('<KeyPress-Right>', turn_right)
while True:
draw_ball()
draw_paddle()
tk.update_idletasks()
tk.update()
time.sleep(0.01)
By the way: not always usage of classes makes sense if there is a simpler and sometimes even more intuitive way of achieving the same result.
The init function is a part of a class that is run every time you create an instance of that class. Self makes the variable an attribute to the class, or that it can be accessed in other parts of your code by, for example ball = Ball() print(ball.radius). There is more information here at the documentation: https://docs.python.org/3/tutorial/classes.html#python-scopes-and-namespaces . If you are using object-oriented programming, there aren't any alternatives to self and init. The only way not to use them would be to not use classes in your code.
The self.radius part of the code is creating a variable representing the size of the ball. This link describes how the different points you set creates the shape of the oval: https://anzeljg.github.io/rin2/book2/2405/docs/tkinter/create_oval.html. The short answer is that self.radius creates the size by spacing out the two points of the oval.
I'm trying write PongGame AI with pygame and stable-baselines. Environment is ready and working. For the agent, im using custom env documentation stable-baselines (https://stable-baselines.readthedocs.io/en/master/guide/custom_env.html)
But when i use check environment.py , error occuring which is
"assertion error: reset() method doesnt matching with observation space"
Game is working properly as i said but when i try make this with customEnv the error occuring which i wrote.
Traceback (most recent call last):
File "C:\Users\Goksel\anaconda3\envs\tensor37\lib\site-packages\spyder_kernels\py3compat.py", line 356, in compat_exec
exec(code, globals, locals)
File "c:\users\goksel\desktop\checkenv.py", line 9, in
check_env(env)
File "C:\Users\Goksel\anaconda3\envs\tensor37\lib\site-packages\stable_baselines\common\env_checker.py", line 214, in check_env
_check_returned_values(env, observation_space, action_space)
File "C:\Users\Goksel\anaconda3\envs\tensor37\lib\site-packages\stable_baselines\common\env_checker.py", line 99, in _check_returned_values
_check_obs(obs, observation_space, 'reset')
File "C:\Users\Goksel\anaconda3\envs\tensor37\lib\site-packages\stable_baselines\common\env_checker.py", line 89, in _check_obs
"method does not match the given observation space".format(method_name))
AssertionError: The observation returned by the reset() method does not match the given observation space
files and codes github link for those who want it:
https://github.com/RsGoksel/PongGame-AI.git
video resources which i used:
https://www.youtube.com/watch?v=uKnjGn8fF70&t=1493s
https://www.youtube.com/watch?v=eBCU-tqLGfQ&t=3551s
https://www.youtube.com/watch?v=bD6V3rcr_54&t=934s
import gym
from gym import spaces
import pygame
import random
import numpy as np
HEIGHT = 450
WIDTH = 600
screen = pygame.display.set_mode((WIDTH,HEIGHT))
white = (255,255,255)
black = (0,0,0)
red = (255,0,0)
blue = (50,0,200)
def updatePaddle(action, paddleY):
if action == 0:
paddleY.rect.y -= 4
if action == 1:
return
if action == 2:
paddleY.rect.y += 4
if paddleY.rect.y < 0:
paddleY.rect.y = 0
if paddleY.rect.y > HEIGHT:
paddleY.rect.y = HEIGHT
return paddleY.rect.y
class PongEnv(gym.Env):
metadata = {'render.modes': ['human']}
class paddle(pygame.sprite.Sprite):
def __init__(self,color):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.Surface([WIDTH/40,HEIGHT/4.5])
self.image.fill(color)
self.rect = self.image.get_rect()
class ball(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.Surface([WIDTH/40,WIDTH/40])
self.image.fill(red)
self.rect = self.image.get_rect()
self.Xspeed = 3
self.Yspeed = 3
def __init__(self):
super(PongEnv, self).__init__()
self.reward = 0
self.done = False
self.score = 0
self.action_space = spaces.Discrete(3)
self.observation_space = spaces.Box(low=0, high=255,
shape=(1,HEIGHT, WIDTH), dtype=np.float32)
self.pedal1 = self.paddle(blue)
self.pedal2 = self.paddle(blue)
self.BALL = self.ball()
self.all_sprites = pygame.sprite.Group()
self.all_sprites.add(self.pedal1, self.pedal2, self.BALL)
#paddle1 and paddle2(bot) location
self.pedal1.rect.x = WIDTH/50 #25
self.pedal1.rect.y = random.randint(0,HEIGHT/10)*10 #300
self.pedal2.rect.x = 23*WIDTH/24 #575
self.pedal2.rect.y = random.randint(0,HEIGHT/10)*10
#ball location. at the beginning of each round, the ball's destination flank changes
self.BALL.rect.x = WIDTH/2
self.BALL.rect.y = HEIGHT/4 + random.randint(0, int(3/4*HEIGHT))
self.BALL.Xspeed = random.sample([-self.BALL.Xspeed,self.BALL.Xspeed],1)[0]
self.BALL.Yspeed = random.sample([-self.BALL.Yspeed,self.BALL.Yspeed],1)[0]
def step(self, action):
self.BALL.rect.x += self.BALL.Xspeed
self.BALL.rect.y += self.BALL.Yspeed
self.pedal2.rect.y = self.BALL.rect.y - (WIDTH/40)
if action==0:
#self.pedal1.rect.y -+= 4
updatePaddle(0, self.pedal1)
if action==2:
updatePaddle(2, self.pedal1)
#if ball hits pedal1, score for paddle because its is exactly what we want
if self.pedal1.rect.colliderect(self.BALL.rect):
self.BALL.Xspeed *= -1
self.score += 5
self.reward = self.score
#collider with paddle2
if self.pedal2.rect.colliderect(self.BALL.rect):
self.BALL.Xspeed *= -1
#control for ball and boundries
if self.BALL.rect.y > HEIGHT - (WIDTH/40) or self.BALL.rect.y < WIDTH/200: #435 or self.top.rect.y < 3
self.BALL.Yspeed *= -1
#its negative score for agent.
if self.BALL.rect.x <= WIDTH/120: #self.pedal1.rect.x yazılabilirdi fakat const değişken ile
self.score -= 10
self.reward = self.score
done = True
self.observation = [self.pedal1.rect.x, self.pedal1.rect.y, self.BALL.rect.x, self.BALL.rect.y]
self.observation = np.array(self.observation)
info = {}
return self.observation, self.reward, self.done, info
def reset(self):
self.done = False
self.score = 0
self.pedal1.rect.x = WIDTH/50 #25
self.pedal1.rect.y = random.randint(0,HEIGHT/10)*10 #300
self.pedal2.rect.x = 23*WIDTH/24 #575
self.pedal2.rect.y = random.randint(0,HEIGHT/10)*10
self.BALL.rect.x = WIDTH/2
self.BALL.rect.y = HEIGHT/4 + random.randint(0, int(3/4*HEIGHT))
self.BALL.Xhiz = random.sample([-self.BALL.Xspeed,self.BALL.Xspeed],1)[0]
self.BALL.Yhiz = random.sample([-self.BALL.Yspeed,self.BALL.Yspeed],1)[0]
self.observation = [self.pedal1.rect.x, self.pedal1.rect.y, self.BALL.rect.x, self.BALL.rect.y]
self.observation = np.array(self.observation)
return self.observation # reward, done, info can't be included
def render(self, mode='human'):
self.screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.init()
pygame.display.init()
while True:
pygame.time.delay(10)
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.display.quit()
pygame.quit()
pygame.display.update()
self.ekran.fill(black)
self.all_sprites.draw(self.screen)
#self.step(0)
def close (self):
if self.screen is not None:
pygame.display.quit()
pygame.quit()
and other checkenv.py file:
from stable_baselines.common.env_checker import check_env
from Stable import PongEnv
env = PongEnv()
check_env(env)
error: AssertionError: The observation returned by the `reset()` method does not match the given observation space
I'm trying to code a little Jump´n´Run game in tkinter with canvas and so far its working pretty well, but I have a problem that I cant´t wrap my head around.
Look at these three pictures: on the first the collision works fine - I can jump from one paddle to the other.
On the second picture, you can see that whenever I get under the paddle it doesn't fall down and jumping up is also not possible, probably because i have self.y = 0 in the self.brick collision detection. How could I get this working such that even when its under the paddle it bounces off, because that's important, for example when I start to add the second line of paddles.
My Collision code:
def brick_hit(self, pos):
for brick_line in self.bricks:
for brick in brick_line:
brick_pos = self.gamerootCanvas.coords(brick.id)
try:
if pos[3] > brick_pos[1]:
if pos[2] > brick_pos[0] and pos[0] < brick_pos[2]:
return True
except:
continue
return False
My Full code:
def jump_and_run():
gameroot = Toplevel()
gameroot.title("Game Root")
gameroot.resizable(0, 0)
gameroot.wm_attributes("-topmost", 1)
gamerootCanvas = Canvas(gameroot, width=1800, height=800, bd=0, highlightthickness=0)
gameroot_Background = PhotoImage(file="jumpnrunbackground.png")
gamerootCanvas.create_image(500, 250, image=gameroot_Background)
gamerootCanvas.pack()
gamerootCanvas.update()
class Player:
def __init__(self, gamerootCanvas, bricks, color):
self.gamerootCanvas = gamerootCanvas
self.id = gamerootCanvas.create_rectangle(25,25,0,0, fill=color)
self.gamerootCanvas.move(self.id, 5, 650)
self.bricks = bricks
self.x = 0
self.y = 0
self.gravity = 0.1
self.gamerootCanvas_height = gamerootCanvas.winfo_height()
self.gamerootCanvas_width = gamerootCanvas.winfo_width()
self.gamerootCanvas.bind_all("<KeyPress-Right>", self.move_right)
self.gamerootCanvas.bind_all("<KeyRelease-Right>", self.move_right_stop)
self.gamerootCanvas.bind_all("<KeyPress-Left>", self.move_left)
self.gamerootCanvas.bind_all("<KeyRelease-Left>", self.move_left_stop)
self.gamerootCanvas.bind_all("<KeyPress-Up>", self.jump_)
self.gamerootCanvas.bind_all("<KeyRelease-Up>", self.jump_stop)
self.jump_counter = 0
self.move_counter = 0
def move_player(self):
self.gamerootCanvas.move(self.id, self.x, self.y)
pos = self.gamerootCanvas.coords(self.id)
self.y += self.gravity
if pos[0] <= 0:
self.x = 1
elif pos[2] >= self.gamerootCanvas_width:
self.x = -1
elif pos[1] <= 0:
self.y = 1
elif pos[3] >= self.gamerootCanvas_height:
self.y = 0
elif self.brick_hit(pos) == True:
self.y = 0
def move_right(self, evt):
self.x = 2
def move_right_stop(self, evt):
self.x = 0
def move_left(self, evt):
self.x = -2
def move_left_stop(self, evt):
self.x = 0
def jump_(self, evt):
if self.jump_counter < 2:
self.y = -6
self.jump_counter += 2
def jump_stop(self, evt):
self.y = 0
self.jump_counter = 0
def brick_hit(self, pos):
for brick_line in self.bricks:
for brick in brick_line:
brick_pos = self.gamerootCanvas.coords(brick.id)
try:
if pos[3] > brick_pos[1]:
if pos[2] > brick_pos[0] and pos[0] < brick_pos[2]:
return True
except:
continue
return False
class Bricks1:
def __init__(self, gamerootCanvas, color):
self.gamerootCanvas = gamerootCanvas
self.id = gamerootCanvas.create_rectangle(50, 15, 0, 0, fill=color, width=2)
self.gamerootCanvas.move(self.id, 5, 700)
def generate_bricks():
global bricks
bricks = []
for i in range(0, 1):
b = []
for j in range(0, 14):
Bricks_1 = Bricks1(gamerootCanvas, "Blue")
b.append(Bricks_1)
bricks.append(b)
for i in range(0, 1):
for j in range(0, 14):
gamerootCanvas.move(bricks[i][j].id, 158.2 * j, 40 * i)
generate_bricks()
player1 = Player(gamerootCanvas, bricks, "Red")
while True:
gameroot.update_idletasks()
player1.move_player()
gameroot.update()
gameroot.after(5)
play_gameloop_sound()
gameUI.mainloop()
You should offset yourself from the brick to prevent becoming stuck. When resting on a brick, you should also have an altered state to prevent jittering.
any help you can give me would be great. I am working on a simple game in python. I would like to have a countdown timer running on the screen. Based on other questions answered on this site, I think I have the code mostly correct, the problem I am having is that I am running the timer code using a "for" loop. I am not really sure why it is not working for me at the moment, when I run the game, I do not get any errors, the countdown displays but it has only counted down one second and it sticks on this time (01:29). Any suggestions would be really appreciated. The code that I am struggling with is towards the end of the program in a section called """Timer Countdown""" in the main loop for the game (line 354). Many thanks.
# Ice Hockey Game
from livewires import games, color
from tkinter import*
import pygame
import math, random
import os
import sys
import time
pygame.init()
games.init(screen_width = 1016, screen_height = 511, fps = 50)
################################################################################
"""timer variables"""
################################################################################
clock = pygame.time.Clock()
font = pygame.font.Font(None, 25)
red = ( 255, 0, 0)
frame_count = 0
frame_rate = 50
start_time = 90
done= False
output_string = ""
################################################################################
"""Score display variables"""
################################################################################
right_score = games.Text(value = 0, size = 25, color = color.black,
top = 30, right = games.screen.width - 250,
is_collideable = False)
games.screen.add(right_score)
left_score = games.Text(value = 0, size = 25, color = color.black,
top = 30, right = 250,
is_collideable = False)
games.screen.add(left_score)
player1_message = games.Message(value = "Player 1 Score",
size = 35,
color = color.black,
x = 250,
y = 15,
lifetime = 100000000,
is_collideable = False)
games.screen.add(player1_message)
player2_message = games.Message(value = "Player 2 Score",
size = 35,
color = color.black,
x = 750,
y = 15,
lifetime = 100000000,
is_collideable = False)
games.screen.add(player2_message)
###############################################################################
"""Player 1 and Player 2 WIN messages"""
###############################################################################
p1_won_message = games.Message(value = "Player 1 Wins!!!",
size = 100,
color = color.blue,
x = games.screen.width/2,
y = games.screen.height/2,
lifetime = 500,
after_death = games.screen.quit,
is_collideable = False)
p2_won_message = games.Message(value = "Player 2 Wins!!!",
size = 100,
color = color.blue,
x = games.screen.width/2,
y = games.screen.height/2,
lifetime = 500,
after_death = games.screen.quit,
is_collideable = False)
##############################################################################
"""Goal animation images and functions"""
################################################################################
"""Animation images"""
goal_anim_files = ["Goal_Anim_001.bmp", "Goal_Anim_002.bmp", "Goal_Anim_003.bmp",
"Goal_Anim_004.bmp","Goal_Anim_005.bmp","Goal_Anim_006.bmp",
"Goal_Anim_007.bmp","Goal_Anim_008.bmp","Goal_Anim_009.bmp","Goal_Anim_010.bmp", "Goal_Anim_011.bmp", "Goal_Anim_012.bmp", "Goal_Anim_013.bmp",
"Goal_Anim_014.bmp","Goal_Anim_015.bmp","Goal_Anim_016.bmp",
"Goal_Anim_017.bmp","Goal_Anim_018.bmp","Goal_Anim_019.bmp","Goal_Anim_020.bmp", "Goal_Anim_021.bmp","Goal_Anim_022.bmp", "Goal_Anim_023.bmp",
"Goal_Anim_024.bmp","Goal_Anim_025.bmp"]
def goal_msg_left(self):
global goal_anim_left
goal_anim_left = games.Animation(images = goal_anim_files, x = 250,
y= games.screen.height/2, n_repeats = 1,
repeat_interval = 1, is_collideable = False)
#print("inside goal_msg_left")
def goal_msg_right(self):
global goal_anim_right
goal_anim_right = games.Animation(images = goal_anim_files, x = 750,
y= games.screen.height/2, n_repeats = 1,
repeat_interval = 1, is_collideable = False)
#print("inside goal_msg_right")
class Leftgoalanim(games.Animation):
"""goal animation"""
def update(self):
self.check_collide()
def check_collide(self):
for player1 in self.overlapping_sprites:
player1.handle_player_collide()
for player2 in self.overlapping_sprites:
player2.handle_player_collide()
class Leftgoal(games.Sprite):
def update(self):
self.check_collide()
self.check_goal()
def check_collide(self):
""" Check for collision with puck. """
for puck in self.overlapping_sprites:
puck.handle_collide()
def handle_collide(self):
""" Move to a random screen location. """
self.dx = -self.dx
self.dy = 0
self.x = games.screen.width/2
self.y = games.screen.height/2
def check_goal(self):
""" Check if left goal. """
global goal_anim_left
for puck in self.overlapping_sprites:
#puck.handle_collide()
goal_msg_left(self)
games.screen.add(goal_anim_left)
right_score.value += 1
if right_score.value >= 10:
games.screen.add(p2_won_message)
class Rightgoal(games.Sprite):
def update(self):
self.check_collide()
self.check_goal()
def check_collide(self):
""" Check for collision with puck. """
for puck in self.overlapping_sprites:
puck.handle_collide()
def handle_collide(self):
""" Move to a random screen location. """
self.dx = -self.dx
self.dy = 0
self.x = games.screen.width/2
self.y = games.screen.height/2
def check_goal(self):
""" Check if left goal. """
for puck in self.overlapping_sprites:
#puck.handle_collide()
goal_msg_right(self)
games.screen.add(goal_anim_right)
left_score.value += 1
if left_score.value >= 10:
games.screen.add(p1_won_message)
################################################################################
"""Classes for Players sprites"""
################################################################################
class Player1(games.Sprite):
"""move the player 1"""
VELOCITY_STEP = .03
VELOCITY_MAX = 3
def update(self):
if games.keyboard.is_pressed(games.K_w):
self.y -= 3
if games.keyboard.is_pressed(games.K_s):
self.y += 3
if games.keyboard.is_pressed(games.K_a):
self.x -= 3
if games.keyboard.is_pressed(games.K_d):
self.x += 3
if self.right > 940:
self.x = 913
if self.left < 85:
self.x = 108
if self.bottom > games.screen.height:
self.y = 475
if self.top < 0:
self.y = 50
self.check_collide()
def check_collide(self):
""" Check for collision with puck. """
for puck in self.overlapping_sprites:
puck.handle_collide()
def handle_player_collide(self):
self.dx = -self.dx
self.dy = 0
def handle_collide(self):
""" Move to a random screen location. """
self.dx = -self.dx
self.dy = 0
class Player2(games.Sprite):
"""move the player 2"""
VELOCITY_STEP = .03
VELOCITY_MAX = 3
def update(self):
if games.keyboard.is_pressed(games.K_UP):
self.y -= 3
if games.keyboard.is_pressed(games.K_DOWN):
self.y += 3
if games.keyboard.is_pressed(games.K_LEFT):
self.x -= 3
if games.keyboard.is_pressed(games.K_RIGHT):
self.x += 3
if self.right > 940:
self.x = 913
if self.left < 85:
self.x = 108
if self.bottom > games.screen.height:
self.y = 475
if self.top < 0:
self.y = 50
self.check_collide()
def check_collide(self):
""" Check for collision with puck. """
for puck in self.overlapping_sprites:
puck.handle_collide()
def handle_collide(self):
""" Move to a random screen location. """
self.dx = -self.dx
self.dy = 0
def handle_player_collide(self):
self.dx = -self.dx
self.dy = 0
################################################################################
"""Class for Puck"""
################################################################################
class Puck(games.Sprite):
""" A bouncing puck. """
def update(self):
""" Reverse a velocity component if edge of screen reached. """
if self.right > games.screen.width or self.left < 0:
self.dx = -self.dx
if self.bottom > games.screen.height or self.top < 0:
self.dy = -self.dy
def handle_collide(self):
""" reverses x direction when collides. """
self.dx = -self.dx
self.dy = self.dy
def handle_goal(self):
"""what happens to the puck when goal"""
self.dx = -self.dx
self.dy = self.dy
################################################################################
"""Main Loop For Game"""
################################################################################
def main():
wall_image = games.load_image("Table_002_1016H_511W.jpg", transparent = False)
games.screen.background = wall_image
#########image left and right goal images and add them to game##########
left_goal_image = games.load_image("Goal_left_cropped.bmp")
the_left_goal = Leftgoal(image = left_goal_image,
x = 40,
y = games.screen.height/2,
)
right_goal_image = games.load_image("Goal_right_cropped.bmp")
the_right_goal = Rightgoal(image = right_goal_image,
x = 976,
y = games.screen.height/2,
)
#########player 1 import image and add to game##########################
player1_image = games.load_image("Player_red_half_50_75_Fixed.bmp")
the_player1 = Player1(image = player1_image,
x = games.screen.width/4,
y = games.screen.height/2)
games.screen.add(the_player1)
#########player 2 import image and add to game##########################
player2_image = games.load_image("Player_green_half_50_75_flipped_fixed.bmp")
the_player2 = Player2(image = player2_image,
x = 750,
y = games.screen.height/2)
games.screen.add(the_player2)
################Import image for the Puck and Add to the game###########
puck_image = games.load_image("puck_small.png", transparent = True)
the_puck = Puck(image = puck_image,
x = games.screen.width/2,
y = games.screen.height/2,
dx = -3,
dy = 3)
counter = 0
###########################################################################
"""TIMER COUNTDOWN"""
###########################################################################
clock = pygame.time.Clock()
font = pygame.font.Font(None, 25)
red = ( 255, 0, 0)
frame_count = 0
frame_rate = 50
start_time = 90
done= False
output_string = ""
for n in reversed(range(0, start_time)):
total_seconds = frame_count // frame_rate
minutes = total_seconds // 60
seconds = total_seconds % 60
output_string = "Time: {0:02}:{1:02}".format(minutes, seconds)
# Blit to the screen
text = font.render(output_string, True, red)
#screen.blit(text, [250, 250])
# --- Timer going down ---
# --- Timer going up ---
# Calculate total seconds
total_seconds = start_time - (frame_count // frame_rate)
if total_seconds < 0:
total_seconds = 0
# Divide by 60 to get total minutes
minutes = total_seconds // 60
# Use modulus (remainder) to get seconds
seconds = total_seconds % 60
# Use python string formatting to format in leading zeros
output_string = "Time left: {0:02}:{1:02}".format(minutes, seconds)
# Blit to the screen
text = font.render(output_string, True, red)
#screen.blit(text, [250, 280])
# ALL CODE TO DRAW SHOULD GO ABOVE THIS COMMENT
frame_count += 1
# Limit to 20 frames per second
clock.tick_busy_loop(50)
# Go ahead and update the screen with what we've drawn.
pygame.display.flip()
###Timer Display###
timer_text = games.Message(value = "TIME",
size = 45,
color = color.red,
top = 30, right = games.screen.width/2,
lifetime = 100000000,
is_collideable = False)
timer_countdown = games.Text(value = output_string, size = 25, color = color.red,
top = 60, right = 600,
is_collideable = False)
games.screen.add(timer_countdown)
games.screen.add(timer_text)
games.screen.add(the_left_goal)
games.screen.add(the_right_goal)
games.screen.add(the_puck)
games.screen.event_grab = True
games.mouse.is_visible = False
games.screen.mainloop()
# start the game
main()
Using pygame.time.get_ticks() to store a start time,
calling this again every frame will give a time greater than your stored start time, simply subtract your start time from this to get the interval in milliseconds since the timer started
As #jonrsharpe said however, it should be a code "sample", not the whole sodding thing, As such I might not have actually answered your question, I can't tell because I'm not going to read and understand the whole code.
The game is simple where the Pan object catches the Pizza objects that are dispensed by the Chef object. When the Pan object (the user) misses a Pizza object, and it hits the floor of the screen, "Game Over" is printed (def game_over(self)) and the game terminates. But after the game terminates, my IDE gives me these error:
Traceback (most recent call last):
File "C:\Users\COMPAQ\My Documents\Aptana Studio Workspace\Pythonic Things\PizzaPanicAttempt\PizzaPanicAttempt3.py", line 125, in <module>
main()
File "C:\Users\COMPAQ\My Documents\Aptana Studio Workspace\Pythonic Things\PizzaPanicAttempt\PizzaPanicAttempt3.py", line 124, in main
games.screen.mainloop()
File "C:\Python27\lib\site-packages\livewires\games.py", line 308, in mainloop
object._tick()
File "C:\Python27\lib\site-packages\livewires\games.py", line 506, in _tick
self.update()
File "C:\Users\COMPAQ\My Documents\Aptana Studio Workspace\Pythonic Things\PizzaPanicAttempt\PizzaPanicAttempt3.py", line 67, in update
self.check_collision()
File "C:\Users\COMPAQ\My Documents\Aptana Studio Workspace\Pythonic Things\PizzaPanicAttempt\PizzaPanicAttempt3.py", line 72, in check_collision
Pizza.handle_caught()
AttributeError: 'Pan' object has no attribute 'handle_caught'
The actual code for the program is as follows:
'''
Created on Jul 1, 2011
#author: ******** Louis
'''
#Watch me do.
from livewires import games, color
import random
games.init (screen_width = 640, screen_height = 480, fps = 50)
#Pizza Class
class Pizza (games.Sprite):
pizzaimage = games.load_image ("pizza.bmp", transparent = True)
def __init__(self, x, y = 90, dy = 4):
super (Pizza, self).__init__(x = x,
y = y,
image = Pizza.pizzaimage,
dy = dy)
def update (self):
if self.bottom>640:
self.game_over()
self.destroy()
def handle_caught (self):
self.destroy()
def game_over (self):
gameovermessage = games.Message(value = "Game Over",
size = 90,
color = color.red,
x = 320,
y = 240,
lifetime = 250,
after_death = games.screen.quit())
games.screen.add(gameovermessage)
#Pan/Cursorial Class
class Pan (games.Sprite):
panimage = games.load_image ("pan.bmp", transparent = True)
def __init__ (self, x = games.mouse.x, y = games.mouse.y):
super (Pan, self).__init__(x = x,
y = y,
image = Pan.panimage)
self.score = 0
self.textbox = games.Text (value = self.score,
size = 20,
color = color.black,
x = 550,
y = 50)
games.screen.add(self.textbox)
def update (self): #WWWWOW There is actually an *update* method
self.x = games.mouse.x
self.y = games.mouse.y
if self.left < 0:
self.left = 0
if self.right >640:
self.right = 640
if self.top < 0:
self.top = 0
if self.bottom > 480:
self.bottom = 480
self.check_collision()
def check_collision (self):
for Pizza in self.overlapping_sprites:
self.textbox.value += 10
Pizza.handle_caught()
#The Pizza Dispenser Class!
class Chef (games.Sprite):
chefimage = games.load_image ("chef.bmp", transparent = True)
def __init__(self, y = 55):
super (Chef, self).__init__(x = 320,
y = y,
dx = 2,
image = Chef.chefimage)
self.timervar = 0
def update (self):
if self.left < 0 or self.right > 640 or random.randrange(50) == 7:
self.dx = -self.dx
self.check_drop()
def check_drop (self):
if self.timervar > 0:
self.timervar = self.timervar - 1
else:
le_pizza = Pizza (x = self.x)
games.screen.add(le_pizza)
self.timervar = 100
#main
def main():
wallimage = games.load_image ("wall.jpg", transparent = True)
games.screen.background = wallimage
games.screen.add (Chef())
games.screen.add (Pan())
games.mouse.is_visible = False
games.screen.event_grab = True
games.screen.mainloop()
main()
#main
def main():
wallbackground = games.load_image ("wall.jpg", transparent = False)
games.screen.background = wallbackground
games.screen.add(Chef())
games.screen.add(Pan())
games.mouse.is_visible = False
games.screen.event_grab = True
games.screen.mainloop()
main()
One of your self.overlapping_sprites is a Pan, not a Pizza.
Also, you have two main()s.