created this game called snake.I was wondering if anyone can help me create a window before the game opens, which contains the start button, exit button and instructions manual so that when i click start, the game starts and when I click exit, the game is terminated. I would also like a try again button that loops the game when the player loses the game, and a quit button which terminates the program. Here is the code for my snake game
from tkinter import*
import random
#Globals
WIDTH = 800
HEIGHT = 600
SEG_SIZE = 20
IN_GAME = True
#Helper Functions
def create_block():
""" Creates an apple to be eaten """
global BLOCK
posx = SEG_SIZE * random.randint(1, (WIDTH-SEG_SIZE) / SEG_SIZE)
posy = SEG_SIZE * random.randint(1, (HEIGHT-SEG_SIZE) / SEG_SIZE)
BLOCK = c.create_oval(posx, posy,
posx+SEG_SIZE, posy+SEG_SIZE,
fill="blue")
def main():
""" Handles game process """
global IN_GAME
if IN_GAME:
s.move()
head_coords = c.coords(s.segments[-1].instance)
x1, y1, x2, y2 = head_coords
#Collision with borders
if x2 > WIDTH or x1 < 0 or y1 < 0 or y2 > HEIGHT:
IN_GAME = False
#Eating apples
elif head_coords == c.coords(BLOCK):
s.add_segment()
c.delete(BLOCK)
create_block()
#Self-eating
else:
for index in range(len(s.segments)-1):
if head_coords == c.coords(s.segments[index].instance):
IN_GAME = False
root.after(100, main)
# NOT IN_GAME -> stop game and print message
else:
c.create_text(WIDTH/2, HEIGHT/2,
text="GAME OVER!",
font="Arial 40",
fill="blue")
class Segment(object):
""" Single snake segment """
def __init__(self, x, y):
self.instance = c.create_rectangle(x, y,
x+SEG_SIZE, y+SEG_SIZE,
fill="black")
class Snake(object):
""" Simple Snake class """
def __init__(self, segments):
self.segments = segments
#possible moves
self.mapping = {"Down": (0, 1), "Right": (1, 0),
"Up": (0, -1), "Left": (-1, 0)}
#initial movement direction
self.vector = self.mapping["Right"]
def move(self):
""" Moves the snake with the specified vector """
for index in range(len(self.segments)-1):
segment = self.segments[index].instance
x1, y1, x2, y2 = c.coords(self.segments[index+1].instance)
c.coords(segment, x1, y1, x2, y2)
x1, y1, x2, y2 = c.coords(self.segments[-2].instance)
c.coords(self.segments[-1].instance,
x1+self.vector[0]*SEG_SIZE, y1+self.vector[1]*SEG_SIZE,
x2+self.vector[0]*SEG_SIZE, y2+self.vector[1]*SEG_SIZE)
def add_segment(self):
""" Adds segment to the snake """
last_seg = c.coords(self.segments[0].instance)
x = last_seg[2] - SEG_SIZE
y = last_seg[3] - SEG_SIZE
self.segments.insert(0, Segment(x, y))
def change_direction(self, event):
""" Changes direction of snake """
if event.keysym in self.mapping:
self.vector = self.mapping[event.keysym]
#Setting up window
root = Tk()
root.title("Snake")
c = Canvas(root, width=WIDTH, height=HEIGHT)
c.grid()
# catch keypressing
c.focus_set()
#creating segments and snake
segments = [Segment(SEG_SIZE, SEG_SIZE),
Segment(SEG_SIZE*2, SEG_SIZE),
Segment(SEG_SIZE*3, SEG_SIZE)]
s = Snake(segments)
#Reaction when key is pressed
c.bind("<KeyPress>", s.change_direction)
#Quitting the game
create_block()
main()
root.mainloop()
Related
This question already has answers here:
Using global variables in a function
(25 answers)
Closed 1 year ago.
I have been programming a python snake game using tkinter canvas and have been running into this error whilst trying to change the tickspeed for every apple eaten. Would be much appreciated if anyone could help as I am quite new to using tkinter and python in general.
File "c:\Users\Admin\Documents\pythonsnake.py", line 45, in main
root.after(Tickspeed, main)
UnboundLocalError: local variable 'Tickspeed' referenced before assignment
This is my code:
#Python Snake Game
from tkinter import Tk, Canvas
import random
import time
# Globals
WIDTH = 800
HEIGHT = 600
SEG_SIZE = 20
IN_GAME = True
Tickspeed = 100
# Helper functions
def create_block():
""" Creates an apple to be eaten """
global BLOCK
posx = SEG_SIZE * random.randint(1, (WIDTH-SEG_SIZE) / SEG_SIZE)
posy = SEG_SIZE * random.randint(1, (HEIGHT-SEG_SIZE) / SEG_SIZE)
BLOCK = c.create_oval(posx, posy,
posx+SEG_SIZE, posy+SEG_SIZE,
fill="red")
def main():
""" Handles game process """
global IN_GAME
if IN_GAME:
s.move()
head_coords = c.coords(s.segments[-1].instance)
x1, y1, x2, y2 = head_coords
# Check for collision with gamefield edges
if x2 > WIDTH or x1 < 0 or y1 < 0 or y2 > HEIGHT:
IN_GAME = False
# Eating apples
elif head_coords == c.coords(BLOCK):
s.add_segment()
c.delete(BLOCK)
if(Tickspeed>20):
Tickspeed = Tickspeed - 5
create_block()
# Self-eating
else:
for index in range(len(s.segments)-1):
if head_coords == c.coords(s.segments[index].instance):
IN_GAME = False
root.after(Tickspeed, main)
# Not IN_GAME -> stop game and print message
else:
set_state(restart_text, 'normal')
set_state(game_over_text, 'normal')
class Segment(object):
""" Single snake segment """
def __init__(self, x, y):
self.instance = c.create_rectangle(x, y,
x+SEG_SIZE, y+SEG_SIZE,
fill="white")
class Snake(object):
""" Simple Snake class convertable """
def __init__(self, segments):
self.segments = segments
# possible moves
self.mapping = {"Down": (0, 1), "Right": (1, 0),
"Up": (0, -1), "Left": (-1, 0)}
# initial movement direction
self.vector = self.mapping["Right"]
def move(self):
""" Moves the snake with the specified vector"""
for index in range(len(self.segments)-1):
segment = self.segments[index].instance
x1, y1, x2, y2 = c.coords(self.segments[index+1].instance)
c.coords(segment, x1, y1, x2, y2)
x1, y1, x2, y2 = c.coords(self.segments[-2].instance)
c.coords(self.segments[-1].instance,
x1+self.vector[0]*SEG_SIZE, y1+self.vector[1]*SEG_SIZE,
x2+self.vector[0]*SEG_SIZE, y2+self.vector[1]*SEG_SIZE)
def add_segment(self):
""" Adds segment to the snake """
last_seg = c.coords(self.segments[0].instance)
x = last_seg[2] - SEG_SIZE
y = last_seg[3] - SEG_SIZE
self.segments.insert(0, Segment(x, y))
def change_direction(self, event):
""" Changes direction of snake """
if event.keysym in self.mapping:
self.vector = self.mapping[event.keysym]
def reset_snake(self):
for segment in self.segments:
c.delete(segment.instance)
def set_state(item, state):
c.itemconfigure(item, state=state)
def clicked(event):
global IN_GAME
s.reset_snake()
IN_GAME = True
c.delete(BLOCK)
c.itemconfigure(restart_text, state='hidden')
c.itemconfigure(game_over_text, state='hidden')
start_game()
def start_game():
global s
create_block()
s = create_snake()
# Reaction on keypress
c.bind("<KeyPress>", s.change_direction)
main()
def create_snake():
# creating segments and snake
segments = [Segment(SEG_SIZE, SEG_SIZE),
Segment(SEG_SIZE*2, SEG_SIZE),
Segment(SEG_SIZE*3, SEG_SIZE)]
return Snake(segments)
# Setting up window cause fun yeah
root = Tk()
root.title("Python Snake Game By Amiel, Amitoj and Abdullah")
c = Canvas(root, width=WIDTH, height=HEIGHT, bg="#003344")
c.grid()
# catch keypressing
c.focus_set()
game_over_text = c.create_text(WIDTH/2, HEIGHT/2, text="GAME OVER!",
font='Calibi 30', fill='red',
state='hidden')
restart_text = c.create_text(WIDTH/2, HEIGHT-HEIGHT/3,
font='Arial 30',
fill='Black',
text=" Click here to restart" + '\n Made by Amiel & Amitoj & Abdullah',
state='hidden')
c.tag_bind(restart_text, "<Button-1>", clicked)
start_game()
root.mainloop()
Here is the fixed code my slime, The print(Tickspeed) is only for ease of dev - Tojinio:
from tkinter import Tk, Canvas
import random
# Globals
WIDTH = 800
HEIGHT = 600
SEG_SIZE = 20
IN_GAME = True
Tickspeed = float(input('Tickspeed: '))
# Helper functions
def create_block():
""" Creates an apple to be eaten """
global BLOCK
posx = SEG_SIZE * random.randint(1, (WIDTH-SEG_SIZE) / SEG_SIZE)
posy = SEG_SIZE * random.randint(1, (HEIGHT-SEG_SIZE) / SEG_SIZE)
BLOCK = c.create_oval(posx, posy,
posx+SEG_SIZE, posy+SEG_SIZE,
fill="red")
def main():
""" Handles game process """
global IN_GAME
global Tickspeed
if IN_GAME:
s.move()
head_coords = c.coords(s.segments[-1].instance)
x1, y1, x2, y2 = head_coords
# Check for collision with gamefield edges
if x2 > WIDTH or x1 < 0 or y1 < 0 or y2 > HEIGHT:
IN_GAME = False
# Eating apples
elif head_coords == c.coords(BLOCK):
s.add_segment()
c.delete(BLOCK)
float(Tickspeed)
# Ramping
if(Tickspeed > 20):
Tickspeed -= 5
Tickspeed1 = Tickspeed
str(Tickspeed1)
print('Your Tickspeed Is: ' + Tickspeed)
create_block()
# Self-eating
else:
for index in range(len(s.segments)-1):
if head_coords == c.coords(s.segments[index].instance):
IN_GAME = False
root.after(100, main)
# Not IN_GAME -> stop game and print message
else:
set_state(restart_text, 'normal')
set_state(game_over_text, 'normal')
class Segment(object):
""" Single snake segment """
def __init__(self, x, y):
self.instance = c.create_rectangle(x, y,
x+SEG_SIZE, y+SEG_SIZE,
fill="white")
class Snake(object):
""" Simple Snake class """
def __init__(self, segments):
self.segments = segments
# possible moves
self.mapping = {"Down": (0, 1), "Right": (1, 0),
"Up": (0, -1), "Left": (-1, 0)}
# initial movement direction
self.vector = self.mapping["Right"]
def move(self):
""" Moves the snake with the specified vector"""
for index in range(len(self.segments)-1):
segment = self.segments[index].instance
x1, y1, x2, y2 = c.coords(self.segments[index+1].instance)
c.coords(segment, x1, y1, x2, y2)
x1, y1, x2, y2 = c.coords(self.segments[-2].instance)
c.coords(self.segments[-1].instance,
x1+self.vector[0]*SEG_SIZE, y1+self.vector[1]*SEG_SIZE,
x2+self.vector[0]*SEG_SIZE, y2+self.vector[1]*SEG_SIZE)
def add_segment(self):
""" Adds segment to the snake """
last_seg = c.coords(self.segments[0].instance)
x = last_seg[2] - SEG_SIZE
y = last_seg[3] - SEG_SIZE
self.segments.insert(0, Segment(x, y))
def change_direction(self, event):
""" Changes direction of snake """
if event.keysym in self.mapping:
self.vector = self.mapping[event.keysym]
def reset_snake(self):
for segment in self.segments:
c.delete(segment.instance)
def set_state(item, state):
c.itemconfigure(item, state=state)
def clicked(event):
global IN_GAME
s.reset_snake()
IN_GAME = True
c.delete(BLOCK)
c.itemconfigure(restart_text, state='hidden')
c.itemconfigure(game_over_text, state='hidden')
start_game()
def start_game():
global Tickspeed
global s
Tickspeed = 100
create_block()
s = create_snake()
# Reaction on keypress
c.bind("<KeyPress>", s.change_direction)
main()
def create_snake():
# creating segments and snake
segments = [Segment(SEG_SIZE, SEG_SIZE),
Segment(SEG_SIZE*2, SEG_SIZE),
Segment(SEG_SIZE*3, SEG_SIZE)]
return Snake(segments)
# Setting up window
root = Tk()
root.title("py snakeĀ© by Amitoj, Amiel and Abdullah")
c = Canvas(root, width=WIDTH, height=HEIGHT, bg="#003344")
c.grid()
# catch keypressing
c.focus_set()
game_over_text = c.create_text(WIDTH/2, HEIGHT/2, text="GAME OVER!",
font='Arial 30', fill='red',
state='hidden')
restart_text = c.create_text(WIDTH/2, HEIGHT-HEIGHT/3,
font='Arial 30',
fill='black',
text=" Click here to restart" + '\n Made by Amitoj, Amiel ' + '\n and Abdullah',
state='hidden')
c.tag_bind(restart_text, "<Button-1>", clicked)
start_game()
root.mainloop()
I'm making a basic game. I want the ball to bounce back up ONLY when it hits the platform. So far, I've written code that will make the ball bounce off the top and bottom screen, but I'm having trouble with getting the ball to bounce off the platform.
from tkinter import *
import time
import tkinter
tk = Tk()
canvas = Canvas(tk, bg="white",width=(900),height=(500))
canvas.pack()
platform = canvas.create_rectangle(400,400,500,410)
def ball():
xspeed = 2
yspeed = 2
ball = canvas.create_oval(430,10,470,50)
while True:
canvas.move(ball, xspeed, yspeed)
pos = canvas.coords(ball)
if pos[2] >=900 or pos[0] <0:
xspeed = -xspeed
tk.update()
time.sleep(0.01)
def board():
board_right()
board_left()
def board_right(event):
xspeed = 5
yspeed = 0
canvas.move(platform,xspeed,yspeed)
tk.update
time.sleep(0.01)
def board_left(event):
xspeed = 5
yspeed = 0
canvas.move(platform,-xspeed,yspeed)
tk.update()
time.sleep(0.01)
canvas.bind_all("<Right>",board_right)
canvas.bind_all("<Left>",board_left)
ball()
tk.mainloop()
Do not use time.sleep() as it will block the tkinter mainloop, use after() instead.
To check whether the ball hits the platform, you need to get the center x of the ball and the lower y of the ball. If center x is within the left and right of platform and the ball lower y is the platform upper y, then reverse the ball y speed. Otherwise game over!
Below is sample code based on yours:
import tkinter as tk
root = tk.Tk()
width = 900
height = 500
canvas = tk.Canvas(root, bg='white', width=width, height=height)
canvas.pack()
ball = canvas.create_oval(430, 10, 470, 50, fill='green')
platform_y = height - 20
platform = canvas.create_rectangle(width//2-50, platform_y, width//2+50, platform_y+10, fill='black')
# ball moving speed
xspeed = yspeed = 2
def move_ball():
global xspeed, yspeed
x1, y1, x2, y2 = canvas.coords(ball)
if x1 <= 0 or x2 >= width:
# hit wall, reverse x speed
xspeed = -xspeed
if y1 <= 0:
# hit top wall
yspeed = 2
elif y2 >= platform_y:
# calculate center x of the ball
cx = (x1 + x2) // 2
# check whether platform is hit
px1, _, px2, _ = canvas.coords(platform)
if px1 <= cx <= px2:
yspeed = -2
else:
canvas.create_text(width//2, height//2, text='Game Over', font=('Arial Bold', 32), fill='red')
return
canvas.move(ball, xspeed, yspeed)
canvas.after(20, move_ball)
def board_right(event):
x1, y1, x2, y2 = canvas.coords(platform)
# make sure the platform is not moved beyond right wall
if x2 < width:
dx = min(width-x2, 10)
canvas.move(platform, dx, 0)
def board_left(event):
x1, y1, x2, y2 = canvas.coords(platform)
# make sure the platform is not moved beyond left wall
if x1 > 0:
dx = min(x1, 10)
canvas.move(platform, -dx, 0)
canvas.bind_all('<Right>', board_right)
canvas.bind_all('<Left>', board_left)
move_ball()
root.mainloop()
New to programming. Working on a simple pong clone. Started the ball but want to make sure all sides of the window (500x500) will have the ball bounce off of it. How could I do this? Thanks!
P.S. This is my current code if needed.
import threading
import random
import time
import string
import os.path
from random import randint
from tkinter import *
class Pong:
Title = 'Pong'
Size = '500x500'
class Ball:
def __init__(self,canvas,x1,y1,x2,y2):
self.x1 =x1
self.y1 = y1
self.x2 = x2
self.y2 = y2
self.canvas = canvas
self.ball = canvas.create_oval(self.x1, self.y1, self.x2, self.y2, fill="black")
def move_ball(self):
deltax = randint(0,5)
deltay = randint(0,5)
self.canvas.move(self.ball,deltax,deltay)
self.canvas.after(50,self.move_ball)
def PongGame():
print("Moved to PongGame.")
ball1 = Ball(canvas,10,10,30,30)
ball1.move_ball()
def titleButtonClicked(event):
print("Title screen button clicked.")
btn.pack_forget()
btn.place(x=600,y=600)
msg.pack_forget()
PongGame()
root = Tk()
root.geometry(Pong.Size)
root.title(Pong.Title)
root.resizable(False,False)
msg = Label(root, text = Pong.Title, font = ("", 50))
msg.pack()
canvas = Canvas(root, width = 500, height = 500)
canvas.pack()
btn=Button(root, text = "Start")
btn.bind('<Button-1>', titleButtonClicked)
btn.place(x=220,y=300)
root.mainloop()
Collisions are not trivial; the simplest is to reverse the x or the y velocity after checking which edge of the bounding box of the ball intersects with the boundaries of the canvas.
Maybe something like this:
import random
import tkinter as tk
WIDTH, HEIGHT = 500, 500
class Ball:
radius = 10
spawn_center = (250, 100)
def __init__(self, canvas):
self.canvas = canvas
self.id = None
self.create_ball()
self.velocity = None
self.assign_random_velocity()
self.keep_moving = True
self.move()
def create_ball(self):
xc, yc = self.spawn_center
x0, y0, = xc - self.radius, yc + self.radius
x1, y1, = xc + self.radius, yc - self.radius
self.id = self.canvas.create_oval(x0, y0, x1, y1)
def assign_random_velocity(self):
dx = random.randrange(1, 5) * random.choice((1, -1))
dy = random.randrange(1, 5) * random.choice((1, -1))
self.velocity = (dx, dy)
def move(self):
if self.keep_moving is None:
return
self.check_collision()
self.canvas.move(self.id, *self.velocity)
self.keep_moving = self.canvas.after(10, self.move)
def cancel_move(self):
if self.keep_moving is not None:
self.canvas.after_cancel(self.keep_moving)
self.keep_moving = None
def check_collision(self):
x0, y0, x1, y1 = self.canvas.coords(self.id)
dx, dy = self.velocity
if x0 < 0:
x0 = 0
dx = -dx
elif x1 > WIDTH:
x1 = WIDTH
dx = -dx
if y0 < 0:
y0 = 0
dy = -dy
elif y1 > HEIGHT:
y1 = HEIGHT
dy = -dy
self.velocity = dx, dy
class PongBoard(tk.Canvas):
def __init__(self, master):
self.master = master
super().__init__(self.master)
self.ball = None
self.spawn_new_ball()
def spawn_new_ball(self):
if self.ball is not None:
self.ball.cancel_move()
self.delete(self.ball.id)
self.ball = Ball(self)
root = Tk()
root.geometry(f'{WIDTH}x{HEIGHT+20}')
board = PongBoard(root)
new_ball_btn = tk.Button(root, text='spawn new ball', command=board.spawn_new_ball)
board.pack(expand=True, fill=tk.BOTH)
new_ball_btn.pack()
root.mainloop()
This will get you started, but you will have to implement the paddles, the paddles movement, the collision checking of the ball with the paddles, and keep the score by yourself.
I have constructed a lattice of particles with tkinter and now I would like each particle in the lattice to move according to a list of x and y coordinates that I read into an array from two text files. I have tried to create a class with a function inside that defines movement with the canvas.move function but I get the error TclError: wrong # coordinates: expected 0 or 4, got 400. How to get around this?
from Tkinter import *
import random
import time
import csv
tk = Tk()
N = 100
T = 500
canvas = Canvas(tk, width=100, height=100)
tk.title("Test")
canvas.pack()
n = 5
t = 10
step1 = []
step2 = []
textFile1 = open('/Users/francislempp/Desktop/major project/C++ programs/Molecular Dynamics 2D/Molecular_Dynamics_2D-gupnvjunowwmjcfiyoursdhzytow/Build/Products/Debug/motionX', 'r')
lines = textFile1.readlines()
for line in lines:
step1.append(line.split(" "))
textFile2 = open('/Users/francislempp/Desktop/major project/C++ programs/Molecular Dynamics 2D/Molecular_Dynamics_2D-gupnvjunowwmjcfiyoursdhzytow/Build/Products/Debug/motionY', 'r')
lines = textFile2.readlines()
for line in lines:
step2.append(line.split(" "))
def moves(xspeed, yspeed):
canvas.move(xspeed, yspeed)
class Ball:
def __init__(self, x, y, color):
self.x = x
self.y = y
self.shape = canvas.create_oval((x,y,x,y), fill = color)
def move(self):
canvas.move(self.shape, self.x, self.y)
pos = canvas.coords(self.shape)
if pos[3] >= 100 or pos[1] <= 0:
self.y = -self.y
if pos[2] > 100 or pos[0] <= 0:
self.x = -self.x
def delete(self):
canvas.delete(self.shape)
balls = []
for x in range(4,100,10):
for y in range(4,100,10):
#canvas.create_oval((x,y,x,y), fill='red')
Ball(x,y,"red")
tk.update()
for i in step1:
for j in step2:
Ball(i,j,"red")
Ball.move()
tk.update()
tk.mainloop()
You have to save items on list and use this list to move
I copy example from previous question
import tkinter as tk
import random
# --- functions ---
def move():
for point_id in points:
x = random.randint(-1, 1)
y = random.randint(-1, 1)
canvas.move(point_id, x, y)
root.after(100, move)
# --- main ---
points = []
root = tk.Tk()
canvas = tk.Canvas(root, width=100, height=100)
canvas.pack()
for x in range(4, 100, 10):
for y in range(4, 100, 10):
point_id = canvas.create_oval(x, y, x, y, fill="red")
points.append(point_id)
move()
root.mainloop()
EDIT: with your class but without data from file.
I use random instead of data from files to show how to create particles and move them.
Every ball moves with own speed/direction which change when touch border.
import tkinter as tk
import random
# --- classes ---
class Ball:
def __init__(self, x, y, speed_x, speed_y, color):
self.speed_x = speed_x
self.speed_y = speed_y
self.shape = canvas.create_oval((x, y, x, y), fill=color)
def move(self):
canvas.move(self.shape, self.speed_x, self.speed_y)
pos = canvas.coords(self.shape)
# change speed/direction when touch border
if pos[3] >= 100 or pos[1] <= 0:
self.speed_y = -self.speed_y
if pos[2] > 100 or pos[0] <= 0:
self.speed_x = -self.speed_x
def delete(self):
canvas.delete(self.shape)
# --- functions ---
def move():
for ball in all_balls:
ball.move()
root.after(100, move)
# --- main ---
root = tk.Tk()
canvas = tk.Canvas(root, width=100, height=100)
canvas.pack()
all_balls = []
for x in range(4, 100, 10):
for y in range(4, 100, 10):
offset_x = random.randint(-2, 2)
offset_y = random.randint(-2, 2)
all_balls.append(Ball(x, y, offset_x, offset_y, "red"))
move()
root.mainloop()
I have no clue how I would implement a game menu into the game I've made, I was thinking about having buttons for instructions credits and a 'play game' button. So would someone mind helping me out in figuring how to make a simple menu in pygame or livewires? Thanks in advance :)
This is the complete code to my game:
# Asteroid Dodger
# Player must avoid asteroids
# make the score a global variable rather than tied to the asteroid.
import pygame
from livewires import games, color
import math, random
#score
games.init(screen_width = 640, screen_height = 480, fps = 50)
score = games.Text(value = 0, size = 25, color = color.green,
top = 5, right = games.screen.width - 10)
games.screen.add(score)
#lives
lives = games.Text(value = 3, size = 25, color = color.green,
top = 5, left = games.screen.width - 620)
games.screen.add(lives)
#inventory
inventory=[]
#Asteroid images
images = [games.load_image("asteroid_small.bmp"),
games.load_image("asteroid_med.bmp"),
games.load_image("asteroid_big.bmp")]
class Ship(games.Sprite):
"""
A Ship controlled by player that explodes when it by Asteroids.
"""
image = games.load_image("player.bmp")
VELOCITY_STEP = .05
def __init__(self):
""" Initialize Ship object """
super(Ship, self).__init__(image = Ship.image,
bottom = games.screen.height)
def update(self):
global inventory
""" uses A and D keys to move the ship """
if games.keyboard.is_pressed(games.K_a):
self.dx -= Ship.VELOCITY_STEP * 2
if games.keyboard.is_pressed(games.K_d):
self.dx += Ship.VELOCITY_STEP * 2
if self.left < 0:
self.left = 0
if self.right > games.screen.width:
self.right = games.screen.width
self.check_collison()
def ship_destroy(self):
self.destroy()
new_explosion = Explosion(x = self.x, y = self.y)
games.screen.add(new_explosion)
def check_collison(self):
""" Check for overlapping sprites in the ship. """
global lives
for items in self.overlapping_sprites:
items.handle_caught()
if lives.value <=0:
self.ship_destroy()
class Explosion(games.Animation):
sound = games.load_sound("explosion.wav")
images = ["explosion1.bmp",
"explosion2.bmp",
"explosion3.bmp",
"explosion4.bmp",
"explosion5.bmp",
"explosion6.bmp",
"explosion7.bmp",
"explosion8.bmp",
"explosion9.bmp"]
def __init__(self, x, y):
super(Explosion, self).__init__(images = Explosion.images,
x = x, y = y,
repeat_interval = 4, n_repeats = 1,
is_collideable = False)
Explosion.sound.play()
class Asteroid(games.Sprite):
global lives
global score
global inventory
"""
A asteroid which falls through space.
"""
image = games.load_image("asteroid_med.bmp")
speed = 3
def __init__(self, x,image, y = 10):
""" Initialize a asteroid object. """
super(Asteroid, self).__init__(image = image,
x = x, y = y,
dy = Asteroid.speed)
def update(self):
""" Check if bottom edge has reached screen bottom. """
if self.bottom>games.screen.height:
self.destroy()
score.value+=10
def handle_caught(self):
if lives.value>0:
lives.value-=1
self.destroy_asteroid()
if lives.value <= 0:
self.destroy_asteroid()
self.end_game()
def destroy_asteroid(self):
self.destroy()
def die(self):
self.destroy()
def end_game(self):
""" End the game. """
end_message = games.Message(value = "Game Over",
size = 90,
color = color.red,
x = games.screen.width/2,
y = games.screen.height/2,
lifetime = 5 * games.screen.fps,
after_death = games.screen.quit)
games.screen.add(end_message)
class Spawner(games.Sprite):
global images
"""
Spawns the asteroids
"""
image = games.load_image("spawner.bmp")
def __init__(self, y = 10, speed = 5, odds_change = 50):
super(Spawner, self).__init__(image = Spawner.image,
x = games.screen.width / 2,
y = y,
dx = speed)
self.odds_change = odds_change
self.time_til_drop = 0
def update(self):
""" Determine if direction needs to be reversed. """
if self.left < 0 or self.right > games.screen.width:
self.dx = -self.dx
elif random.randrange(self.odds_change) == 0:
self.dx = -self.dx
self.check_drop()
self.check_for_lives()
def check_drop(self):
""" Decrease countdown or drop asteroid and reset countdown. """
if self.time_til_drop > 0:
self.time_til_drop -= 0.7
else:
asteroid_size = random.choice(images)
new_asteroid = Asteroid(x = self.x,image = asteroid_size)
games.screen.add(new_asteroid)
# makes it so the asteroid spawns slightly below the spawner
self.time_til_drop = int(new_asteroid.height * 1.3 / Asteroid.speed) + 1
def check_for_lives(self):
droplives = random.randrange(0, 4000)
if droplives == 5:
lifetoken = Extralives(x = self.x)
g ames.screen.add(lifetoken)
class Extralives(games.Sprite):
global lives
image = games.load_image('addlives.png')
speed = 2
sound = games.load_sound("collectlives.wav")
def __init__(self,x,y = 10):
""" Initialize a asteroid object. """
super(Extralives, self).__init__(image = Extralives.image,
x = x, y = y,
dy = Extralives.speed)
def update(self):
""" Check if bottom edge has reached screen bottom. """
if self.bottom>games.screen.height:
self.destroy()
def handle_caught(self):
Extralives.sound.play()
lives.value+=1
self.destroy()
def main():
""" Play the game. """
bg = games.load_image("space.jpg", transparent = False)
games.screen.background = bg
the_spawner = Spawner()
games.screen.add(the_spawner)
pygame.mixer.music.load("Jumpshot.ogg")
pygame.mixer.music.play()
the_ship = Ship()
games.screen.add(the_ship)
games.mouse.is_visible = False
games.screen.event_grab = True
games.screen.mainloop()
#starts the game
main()
The Pygbutton module provides a way to create buttons in Pygame programs. You can download it via "pip install pygbutton". There are demos on the github: https://github.com/asweigart/pygbutton
Try this code out:
Game Menu function
def game_intro():
intro = True
while intro:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
gameDisplay.fill(white)
titleText = gameDisplay.blit(title, (170, 200)) # title is an image
titleText.center = ((display_width / 2), (display_height / 2))
# button(x, y, w, h, inactive, active, action=None)
button(100, 350, 195, 80, startBtn, startBtn_hover, game_loop)
button(300, 350, 195, 80, creditsBtn, creditsBtn_hover, #Your function)
pygame.display.update()
clock.tick(15)
you can call this menu above your game loop.
Button function
Pygame doesn't have buttons but it is pretty easy to make one!
def button(x, y, w, h, inactive, active, action=None):
mouse = pygame.mouse.get_pos()
click = pygame.mouse.get_pressed()
if x + w > mouse[0] > x and y + h > mouse[1] > y:
gameDisplay.blit(active, (x, y))
if click[0] == 1 and action is not None:
action()
else:
gameDisplay.blit(inactive, (x, y))
you can call this function inside your game menu like this:
#Example function call
button(340, 560, 400, 200, randomBtn, randomBtn_hover, random_func)
Here's what each parameter means in button():
x: x-coordinate of button
y: y-coordinate of button
w: button width(in pixels)
h: button height(in pixels)
active: the picture of the button when it is active(e.g when the mouse is hovering ver it)
inactive: the picture of the button when it is idle
action: the function to be executed when the button is pressed
Note: It is better to make a button function since it is easier to make one and it saves a lot of time
Hope this helped!