Skip to content

Instantly share code, notes, and snippets.

@Krewn
Created December 3, 2020 05:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Krewn/073a8cf8ed32d0d78171d409d71c74f0 to your computer and use it in GitHub Desktop.
Save Krewn/073a8cf8ed32d0d78171d409d71c74f0 to your computer and use it in GitHub Desktop.
A small game using python turtle.
"""######################################### Imports ############################################"""
import turtle
import time
import functools
"""######################################### Key press ##########################################"""
def key_space(): # Resets Level
field.setLevel()
def key_p(): # Skips Level
field.nextLevel()
def key_k(): # For making levels
print([(b.x,b.y) for b in field.getBoxes()])
"""######################################## Interface(s) ########################################"""
def stamp(self): # Interface for drawing polygons.
turtle.goto(self.canvasX+field.offset[0],self.canvasY+field.offset[1])
turtle.shape(self.shape)
turtle.color(self.color)
turtle.stamp()
def frameBoiler(func): #
@functools.wraps(func)
def wrapper_frame_boiler(*args,**kwargs):
turtle.clear()
#turtle.getscreen().bgpic('Untitled.png')
r = func(*args, **kwargs)
turtle.update()
time.sleep(0.05)
return r
return wrapper_frame_boiler
"""######################################### Game Logic #########################################"""
class field: # Field is an abstract class which facilitates the game Mechanics
def place(o): # Place translates an objects board position to a pixel or canvas position
o.canvasX = (o.x-31)*field.spaceSize # 31 beacuse it's half of the magic number...
o.canvasY = (o.y-31)*field.spaceSize
return(o) # This method should be a void //TODO refactor...
class square:
padding = 2
color = "#078900"
shape = "sq" # "sq" is the name of the stamp polygon geometry.
#//TODO refactor: eliminate redundant literals. see def turtleSetup
def __init__(self,x,y):
self.x = x
self.y = y
field.place(self)
def draw(self):
stamp(self)
class level: # Levels are what make the game fun.
class mando: # These are the spots you have to populate
thickness = 2 #
trim = 1
color = "#ee0000"
shape = "bx" # "bx" is the name of the stamp polygon geometry.
#//TODO refactor: eliminate redundant literals. see def turtleSetup
def draw(self): # each mando needs to be visable...
stamp(self) # line: 15: `def stamp(self)`
def __init__(self,x,y): # make a mandatory space
self.x = x
self.y = y
self.canvasX = 0 # field isn't visible from this deeply nested class
self.canvasY = 0 # so these are "unplaced"
def __init__(self,text,spots): # make a level
self.text = text
self.mandos = []
self.complete = False
for spot in spots:
self.mandos.append(self.mando(spot[0],spot[1]))
def checkWin(self): # If the boxes on the board match the mandos you beat the level.
oneLiner = set([(b.x,b.y) for b in field.getBoxes()])
isTooLong = set([(m.x,m.y) for m in self.mandos])
self.complete = oneLiner == isTooLong
def draw(self): # This draws the mandos and the level's acompanying text.
for mando in self.mandos:
mando.draw()
if self.complete:
field.nextLevel()
spaces = [[None]*63 for k in range(0,63)] # 63 is the magic number, ralistically it could be 8
levels =[level("letsGo",[(31,33),(31,29),(29,31),(33,31)]),
level("Never\nEat\nShreaded\nWheat",[(27, 31), (28, 30), (28, 32), (29, 30), (29, 32),
(30, 28), (30, 29), (30, 33), (30, 34), (31, 27), (31, 35), (32, 28), (32, 29),
(32, 33), (32, 34), (33, 30), (33, 32), (34, 30), (34, 32), (35, 31)]),
level("Try:\nPress Space",[(29, 31), (30, 30), (31, 31), (31, 33), (32, 29), (33, 32),
(34, 31)]),
level("Flex",[(28, 27), (28, 28), (28, 29), (29, 26), (29, 30), (29, 35), (29, 36),
(30, 29), (30, 31), (30, 33), (30, 34), (30, 35), (30, 37), (31, 28), (31, 29),
(31, 33), (31, 35), (31, 36), (32, 29), (32, 31), (32, 33), (32, 34), (32, 35),
(32, 37), (33, 26), (33, 30), (33, 35), (33, 36), (34, 27), (34, 28), (34, 29)]),
level("Blast Off",[(28, 28), (28, 29), (28, 31), (29, 27), (29, 31), (29, 32), (30, 28),
(30, 29), (30, 31), (30, 32), (30, 33), (30, 34), (31, 33), (31, 35), (32, 28),
(32, 29), (32, 31), (32, 32), (32, 33), (32, 34), (33, 27), (33, 31), (33, 32),
(34, 28), (34, 29), (34, 31)]),
level("Space\nInvaders",[(27, 31), (28, 30), (28, 32), (29, 27), (29, 28), (29, 30),
(29, 31), (30, 26), (30, 28), (30, 29), (30, 33), (31, 27), (31, 28), (31, 31),
(31, 32), (32, 26), (32, 28), (32, 29), (32, 33), (33, 27), (33, 28), (33, 30),
(33, 31), (34, 30), (34, 32), (35, 31)]),
level("big oof",[(31,31),(32,31),(31,33)])]
levelIndex = 0 # literally the number indicating what level you're on
spaceSize = 40 # the number of pixels to a in gmae space.
offset = [-80,0] # you can arbitrailly move the gmae around the screen...
def hit(x,y): # toggle the presence of a box in a space on the board/field.
try:
if field.spaces[x][y] is None:
field.spaces[x][y] = field.place(field.square(x,y))
else:
field.spaces[x][y] = None
except IndexError:
pass
def setLevel(): # clears the board puts a box in the middle and places the mandos.
field.spaces = [[None]*63 for k in range(0,63)]
field.hit(31,31)
[field.place(mando) for mando in field.levels[field.levelIndex].mandos]
def nextLevel(): # the first level is also the level after the last level.
field.levelIndex += 1
if field.levelIndex >= len(field.levels):
field.levelIndex = 0
field.setLevel()
@frameBoiler
def draw(): # this is the draw method for the
field.levels[field.levelIndex].draw()
for box in field.getBoxes():
box.draw()
turtle.color("#bad4af")# // Todo figure out why the text causes a flicker.
turtle.goto(field.levels[field.levelIndex].
mandos[-1].canvasX,field.levels[field.levelIndex].mandos[-1].canvasY)
turtle.write(field.levels[field.levelIndex].text,
font=('Courier', 33, 'italic'), align='left')
def click(x,y):
spacex = int((float(x)-field.offset[0])/field.spaceSize +31) # more magic numbers...
spacey = int((float(y)-field.offset[1])/field.spaceSize +32) # change them I dare you.
try:
field.bop(spacex,spacey)
except IndexError:
pass
field.levels[field.levelIndex].checkWin()
def getBoxes(): # in reality field.spaces should just be a dictionary... // TODO
return sum([[box for box in boxes if not box is None] for boxes in field.spaces],[])
def bop(x,y):
if field.spaces[x][y] is None:
pass
else:
field.hit(x,y)
field.hit(x+1,y)
field.hit(x-1,y)
field.hit(x,y+1)
field.hit(x,y-1)
"""##############################################################################################"""
def turtleSetup():
turtle.tracer(0,0)
turtle.register_shape("sq", # This is a square that denotes the boxes... wait
((field.square.padding,
field.square.padding),
(field.spaceSize-field.square.padding,
field.square.padding),
(field.spaceSize-field.square.padding,
field.spaceSize-field.square.padding),
(field.square.padding,
field.spaceSize-field.square.padding)))
turtle.register_shape("bx", # this is a box that is used to denote the mandos... woops.
((field.level.mando.trim,field.level.mando.trim),
(field.level.mando.thickness,
field.level.mando.thickness),
(field.spaceSize-field.level.mando.thickness,
field.level.mando.thickness),
(field.spaceSize-field.level.mando.thickness,
field.spaceSize-field.level.mando.thickness),
(field.level.mando.thickness,
field.spaceSize-field.level.mando.thickness),
(field.level.mando.thickness,
field.level.mando.thickness),
(field.level.mando.trim,
field.level.mando.trim),
(field.level.mando.trim,
field.spaceSize-field.level.mando.trim),
(field.spaceSize-field.level.mando.trim,
field.spaceSize-field.level.mando.trim),
(field.spaceSize-field.level.mando.trim,
field.level.mando.trim)))
turtle.ht() # Hide Turtle so you don't get a indicator on the rendering mechanism
turtle.pu() # Pen up so you don't see the path of the rendering mechanism.
turtle.onkey(key_space, "space") # Register key events.
turtle.onkey(key_k, "k")
turtle.onkey(key_p, "q")
turtle.getscreen().onclick(field.click) # register the click event
turtle.listen() # this probably needs to be here for some reason, idk delete it & see for yaself
"""##############################################################################################"""
class main:
def __init__(self):
turtleSetup()
field.setLevel()
while None is None:
field.draw()
main() # Look at how clean that main function is!
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment