Цель игры - провести игрового персонажа (зайца) как можно дальше через бесконечное поле, полное железнодорожных путей. Путь для героя осложняют многочисленные кустарники, преграждающие путь и скоростные поезда, которые могут переехать героя.
Основные текстуры, используемые в игре нужно скачать с github оригинальной игры: https://github.com/Wireframe-Magazine/Code-the-Classics/tree/master/bunner-master/images
from tkinter import *
from random import randint, shuffle, choice
from time import time
from tkinter import messagebox
root = Tk()
canvas = Canvas(root, bg="yellow",
height=560, width=480)
imageLib = {
"sit-left": PhotoImage(file=f"textures/sit3.png"),
"sit-right": PhotoImage(file=f"textures/sit1.png"),
"sit-up": PhotoImage(file=f"textures/sit0.png"),
"sit-down": PhotoImage(file=f"textures/sit2.png"),
"rail1": PhotoImage(file=f"textures/rail1.png"),
"rail2": PhotoImage(file=f"textures/rail2.png"),
"rail3": PhotoImage(file=f"textures/rail3.png"),
"train-yellow-l": PhotoImage(file=f"textures/train00.png"),
"train-orange-r": PhotoImage(file=f"textures/train11.png"),
"bush": PhotoImage(file=f"textures/bush31.png"),
"dead": PhotoImage(file=f"textures/splat0.png"),
}
for i in range(7, 15):
imageLib[f"grass{i}"] = PhotoImage(file=f"textures/grass{i}.png")
class GrassRow:
image = False
element = False
train = False
bushes = False
y = -1
def __init__(self, x, y, img="random", bushed=True):
self.y = y
self.image = imageLib[f"grass{randint(7, 14)}"] if img=="random" else imageLib[img]
self.element = canvas.create_image((x, y), image=self.image)
if bushed: self.bushes = [True, True, True, False, False, False, False, False, False, False, False, False]
else:
self.bushes = [False]*12
shuffle(self.bushes)
# print(self.bushes)
for i in range(12):
if self.bushes[i]:
self.bushes[i] = canvas.create_image((i*40+20, self.getY()), image=imageLib["bush"])
# for i in range(50):
# self.trainArrives.append(time()+i*10)
def update(self, dx, dy):
self.y+=dy
canvas.move(self.element, dx, dy)
for i in self.bushes:
if i == False: continue
canvas.move(i, dx, dy)
def getY(self):
# return canvas.coords(self.element)[1]
return self.y
trainSpd = 30
worldY = 0
class RailsRow:
image = imageLib["rail2"]
trainImage = imageLib["train-yellow-l"]
element = False
train = False
trainDir = 1
bushes = [False]*12
y=-1
def __init__(self, x, y):
self.y = y
# self.image = imageLib[f"grass{randint(7, 14)}"]
self.element = canvas.create_image((x, y), image=self.image)
self.trainArrives = time()+randint(2, 5)
def getTrainBounds(self):
halfTrain = self.trainImage.width()/2
tx = canvas.coords(self.train)[0]
ty = self.getY()
return (tx-halfTrain, ty, tx+halfTrain, ty+5)
def update(self, dx, dy):
canvas.move(self.element, dx, dy)
self.y+=dy
if 0 < (time()-self.trainArrives):
canvas.tkraise(self.train)
if self.train== False:
self.trainDir = choice((-1, 1))
self.trainImage = imageLib["train-yellow-l" if self.trainDir == -1 else "train-orange-r"]
self.train = canvas.create_image((480+self.trainImage.width()/2 if self.trainDir == -1 else -self.trainImage.width()/2, self.getY()-20), image=self.trainImage)
else:
# print(trainSpd*self.trainDir, self.trainDir)
canvas.move(self.train, trainSpd*self.trainDir, dy)
if rabbit.element in canvas.find_overlapping(*self.getTrainBounds()):
rabbit.image = imageLib["dead"]
rabbit.changeImage()
messagebox.showerror(message="Заяц сдох!")
exit()
# print("movce")
if (self.trainDir == -1 and canvas.coords(self.train)[0] < -self.trainImage.width()/2) or (self.trainDir == 1 and canvas.coords(self.train)[0] > 480 + self.trainImage.width()/2):
canvas.delete(self.train)
self.train = False
self.trainArrives=time()+randint(2, 5)
def getY(self):
# return canvas.coords(self.element)[1]
return self.y
# for i in range(0, 580, 40):
# GrassRow(240, i)
worldSpeed = 1
class Rabbit:
image = imageLib["sit-up"]
myRow = 4
element = False
posX = 6
def __init__(self):
self.element = canvas.create_image((260, 560-20-160), image=self.image)
canvas.tkraise(self.element)
def changeImage(self):
canvas.itemconfigure(self.element, image=self.image)
def getCellX(self):
# print(int(canvas.coords(self.element)[0]//40), canvas.coords(self.element)[0])
# return int(canvas.coords(self.element)[0]//40)
print(self.posX, self.myRow)
return self.posX
def update(self, dx, dy):
canvas.tkraise(self.element)
if dx>=40:
self.image = imageLib["sit-right"]
if area[self.myRow].bushes[self.getCellX()+1] != False: return
self.posX += 1
if dx<=-40:
self.image = imageLib["sit-left"]
if area[self.myRow].bushes[self.getCellX()-1] != False: return
self.posX -= 1
if dy>=40:
self.image = imageLib["sit-down"]
if area[self.myRow-1].bushes[self.getCellX()] != False: return
self.myRow -= 1
if dy<=-40:
self.image = imageLib["sit-up"]
if area[self.myRow+1].bushes[self.getCellX()] != False: return
self.myRow += 1
# if abs(dy) > worldSpeed: print(dy)
self.changeImage()
canvas.move(self.element, dx, dy)
root.bind("<Up>", lambda _: rabbit.update(0, -40))
root.bind("<Down>", lambda _: rabbit.update(0, 40))
root.bind("<Left>", lambda _: rabbit.update(-40, 0))
root.bind("<Right>", lambda _: rabbit.update(40, 0))
area = [GrassRow(240, 560-20, bushed=False)]
def getNextAreaY():
return area[-1].getY()-40
rabbit = Rabbit()
while len(area) < 20:
type = choice(["rail", "grass"])
if type == "rail":
area.append(GrassRow(240, getNextAreaY(), "rail1"))
area.append(RailsRow(240, getNextAreaY()))
area.append(GrassRow(240, getNextAreaY(), "rail3"))
if type == "grass":
for i in range(randint(0, 3)):
area.append(GrassRow(240, getNextAreaY()))
def updateAll():
if canvas.coords(rabbit.element)[1] < 400: worldSpeed = 400/canvas.coords(rabbit.element)[1]
else: worldSpeed = 1
rabbit.update(0, worldSpeed)
removalList = []
for ID, i in enumerate(area):
i.update(0, worldSpeed)
if i.getY() > 640:
removalList.append(ID)
for ID, i in enumerate(removalList):
if area[i].train: canvas.delete(area[i].train)
canvas.delete(area[i].element)
area.pop(i-ID)
print("pop", i-ID, len(area))
rabbit.myRow -= 1
# print(len(area))
while len(area) < 30:
type = choice(["rail", "grass"])
if type == "rail":
area.append(GrassRow(240, getNextAreaY(), "rail1"))
area.append(RailsRow(240, getNextAreaY()))
area.append(GrassRow(240, getNextAreaY(), "rail3"))
if type == "grass":
for i in range(randint(0, 3)):
area.append(GrassRow(240, getNextAreaY()))
root.after(20, updateAll)
updateAll()
canvas.pack()
mainloop()