Problem when resizing and saving a turtle screen - python

So I could save a big drawing and see its full size in an image visualizer, I resized my turtle window bigger then my monitor size. But the saved image is not being resized, so the drawing is being truncated:
from turtle import Screen, Turtle
import random
screen = Screen()
screen.setup(width=1200, height=2700, startx=None, starty=None)
t = Turtle(visible=False)
t.speed('fastest') # because I have no patience
t2 = Turtle(visible=False)
t2.speed('fastest') # because I have no patience
t3 = Turtle(visible=False)
t3.speed('fastest') # because I have no patience
def got(x, y, d): # to use goto more easily
t.penup()
t.goto(x, y)
t.pendown()
t.seth(d)
def flatoval(r): # Horizontal Oval
t.right(45)
for loop in range(2):
t.circle(r, 90)
t.circle(r / 2, 90)
got(0, -200, 0)
def elipse(r, a, b, c):
for extent in range(9):
rnd = random.randint(1, 20)
# if extent == 0 or extent == 3 or extent == 6 :
# t.color('red')
# if extent == 1 or extent == 4 or extent == 7 :
# t.color('yellow')
# if extent == 2 or extent == 5 or extent == 8 :
# t.color('blue')
t.circle(r, 10)
heading = t.heading()
if extent == 0 or extent == 1 or extent == 2:
# t.color('green')
t.setheading(0)
t.forward(rnd)
t.forward(a)
t.backward(rnd)
t.forward(c)
t.setheading(heading)
def canais(x, y, d, egnar):
for tog in range(egnar):
got(x, y, d)
elipse(100, 0, 0, 0)
elipse(50, 0, 0, 0)
elipse(100, 0, 0, 0)
elipse(50, 0, 0, 0)
d = d + 10
elipse(200, 0, 0, 0)
elipse(100, 0, 0, 0)
elipse(200, 0, 0, 0)
elipse(100, 0, 0, 0)
elipse(300, 0, 0, 0)
elipse(200, 0, 0, 0)
elipse(300, 0, 0, 0)
elipse(200, 0, 0, 0)
canais(0, -100, 0, 40)
ts = t.getscreen()
ts.getcanvas().postscript(file="canais_organizados_separadamente.eps")
I also tried this change:
screen = Screen()
screen.setup(width=1200, height=2700, startx=None, starty=None)
in place of:
screen = Screen()
screen.setup(400, 500)
Truncated image:

By default, the tkinter canvas postscript() method only captures the visible portion of the canvas. You need to tell it, via the width and height arguments, whether you want more than that. Below is your code reworked with that fix and several others to improve the performance and/or simplify the logic:
from turtle import Screen, Turtle
from random import randint
def got(x, y, d): # to use goto more easily
turtle.penup()
turtle.goto(x, y)
turtle.pendown()
turtle.setheading(d)
def flatoval(r): # Horizontal Oval
turtle.right(45)
for _ in range(2):
turtle.circle(r, 90)
turtle.circle(r / 2, 90)
def elipse(r, a, b, c):
for extent in range(9):
rnd = randint(1, 20)
turtle.circle(r, 10)
heading = turtle.heading()
if extent <= 2:
turtle.setheading(0)
turtle.forward(rnd)
turtle.forward(a)
turtle.backward(rnd)
turtle.forward(c)
turtle.setheading(heading)
def canais(x, y, d, egnar):
for _ in range(egnar):
got(x, y, d)
elipse(100, 0, 0, 0)
elipse(50, 0, 0, 0)
elipse(100, 0, 0, 0)
elipse(50, 0, 0, 0)
elipse(200, 0, 0, 0)
elipse(100, 0, 0, 0)
elipse(200, 0, 0, 0)
elipse(100, 0, 0, 0)
elipse(300, 0, 0, 0)
elipse(200, 0, 0, 0)
elipse(300, 0, 0, 0)
elipse(200, 0, 0, 0)
d += 10
screen = Screen()
screen.setup(1200, 1200)
turtle = Turtle(visible=False)
got(0, -200, 0)
screen.tracer(False)
canais(0, -100, 0, 36)
screen.tracer(True)
canvas = screen.getcanvas()
canvas.postscript(file="canais_organizados_separadamente.eps", width=1200, height=1200)

Related

Circuitpython | Traceback ValueError | >BUTTON_A is being used<

Context
I hope I can get some help. Thanks in advance
I recently acquired a Circuit Playground Express as a project for college, and I am having some issues programming with it, specially because the Traceback is constantly giving me an error which I don't know how to fix, and I have tried several things now, and couldn't get anything different.
I am using a IDE for CircuitPython called "Mu Editor" https://codewith.mu/en/download, which provides me some interesting tools that have made my work kind of easier. (I have to clarify I have never coded in Python, so I am kinda lost in everything)
Error
Traceback (ultima llamada reciente):
Archivo "code.py", línea 61, en <module>
ValueError: BUTTON_A está siendo utilizado
El código terminó de ejecutar.
Code which is getting error
I am having the issue specially on these pieces of code:
Variable a_but, which will allow me to use the BUTTON_A of the Circuit Playground, so it does something when it is pressed
a_but = DigitalInOut(board.D4)
a_but.direction = Direction.INPUT
a_but.pull = Pull.DOWN
Variable b_but, which will allow me to use the BUTTON_B of the Circuit Playground, so it does something when it is pressed
b_but = DigitalInOut(board.D5)
b_but.direction = Direction.INPUT
b_but.pull = Pull.DOWN
Variable pixels that will allow me to access to modify the neopixels of the Circuit Playground
pixels = neopixel.NeoPixel(board.NEOPIXEL, 10, brightness=1.0)
Examples of the above variables when being used:
a_but and b_but
while True:
if a_but.value:
print("Button A pressed")
if b_but.value:
print("Button B pressed")
pixels
if temp < 36:
pixels[0] = (0, 0, 255)
pixels[1] = (0, 0, 255)
pixels[2] = (0, 0, 255)
elif temp >= 36 and temp <= 37.2:
pixels[3] = (0, 0, 255)
pixels[4] = (0, 0, 255)
pixels[5] = (0, 0, 255)
pixels[6] = (0, 0, 255)
else:
pixels[7] = (0, 0, 255)
pixels[8] = (0, 0, 255)
pixels[9] = (0, 0, 255)
Here is the complete code in case you want to take a look (It might have some errors since that error is blocking me from moving on):
import time
import analogio
import board
import neopixel
import pulseio
import digitalio
from digitalio import DigitalInOut, Direction, Pull
import adafruit_irremote
import adafruit_thermistor
from adafruit_circuitplayground import cp
def sign(value):
if value > 0:
return 1
if value < 0:
return -1
return 0
def pulse_test():
# Turn only pixel #1 green
pixels[1] = (0, 255, 0)
# How many light readings per sample
NUM_OVERSAMPLE = 10
# How many samples we take to calculate 'average'
NUM_SAMPLES = 20
samples = [0] * NUM_SAMPLES
i = True
while i:
for i in range(NUM_SAMPLES):
# Take NUM_OVERSAMPLE number of readings really fast
oversample = 0
for s in range(NUM_OVERSAMPLE):
oversample += float(light.value)
# and save the aver age from the oversamples
samples[i] = oversample / NUM_OVERSAMPLE # Find the average
mean = sum(samples) / float(len(samples)) # take the average
print((samples[i] - mean,)) # 'center' the reading
if i > 0:
# If the sign of the data has changed munus to plus
# we have one full waveform (2 zero crossings), pulse LED
if sign(samples[i] - mean) <= 0 and sign(samples[i - 1] - mean) > 0:
pixels[9] = (200, 0, 0) # Pulse LED
else:
pixels[9] = (0, 0, 0) # Turn LED off
time.sleep(0.025) # change to go faster/slower
if b_but.value:
i = False
pixels[1] = (0, 0, 0)
pixels[9] = (0, 0, 0)
a_but = DigitalInOut(board.D4)
a_but.direction = Direction.INPUT
a_but.pull = Pull.DOWN
b_but = DigitalInOut(board.D5)
b_but.direction = Direction.INPUT
b_but.pull = Pull.DOWN
pixels = neopixel.NeoPixel(board.NEOPIXEL, 10, brightness=1.0)
light = analogio.AnalogIn(board.LIGHT)
RED = (255, 0, 0)
YELLOW = (255, 255, 0)
GREEN = (0, 255, 0)
CYAN = (0, 255, 255)
BLUE = (0, 0, 255)
PURPLE = (180, 0, 255)
PIXELS_OFF = (0, 0, 0)
pulsein = pulseio.PulseIn(board.IR_RX, maxlen=120, idle_state=True)
decoder = adafruit_irremote.GenericDecode()
while True:
pulse = decoder.read_pulses(pulsein)
try:
received_code = decoder.decode_bits(pulse)
print("\n\nSeñal Adquirida : ", received_code)
if received_code == (223, 32, 111, 144):
print("¡Sospecha de infeccion detectada!\n\n")
for i in range(3):
pixels.fill(YELLOW)
pixels.show()
time.sleep(0.05)
pixels.fill(PIXELS_OFF)
pixels.show()
time.sleep(0.05)
print("¿Desea realizar un testeo basico?:")
print("\n\n Si. Presione A\n No. Presione B")
pixels[0] = (0, 255, 0)
pixels[1] = (0, 255, 0)
pixels[2] = (0, 255, 0)
pixels[3] = (0, 255, 0)
pixels[4] = (0, 255, 0)
pixels[5] = (255, 0, 0)
pixels[6] = (255, 0, 0)
pixels[7] = (255, 0, 0)
pixels[8] = (255, 0, 0)
pixels[9] = (255, 0, 0)
while True:
if a_but.value:
testeo_respuesta = True
for x in range(2):
pixels.fill(PIXELS_OFF)
pixels.show()
for i in range(9):
pixels[10] = (0, 255, 0)
time.sleep(0.075)
break
if b_but.value:
testeo_respuesta = False
for x in range(2):
pixels.fill(PIXELS_OFF)
pixels.show()
for i in range(9):
pixels[i] = (255, 0, 0)
time.sleep(0.075)
break
time.sleep(0.075)
pixels.fill(PIXELS_OFF)
pixels.show()
if testeo_respuesta:
for test_num in range(19):
regTemp = [cp.temperature] * test_num
time.sleep(1.0)
for k in range(19):
pixels[0] = (0, 0, 255)
temp = 0
if temp < regTemp[k]:
temp = regTemp[k]
pixels[0] = (0, 0, 0)
time.sleep(0.5)
if temp < 36:
pixels[0] = (0, 0, 255)
pixels[1] = (0, 0, 255)
pixels[2] = (0, 0, 255)
pixels[3] = (0, 0, 0)
pixels[4] = (0, 0, 0)
pixels[5] = (0, 0, 0)
pixels[6] = (0, 0, 0)
pixels[7] = (0, 0, 0)
pixels[8] = (0, 0, 0)
pixels[9] = (0, 0, 0)
resultado = True
elif temp >= 36 and temp <= 37.2:
pixels[0] = (0, 0, 0)
pixels[1] = (0, 0, 0)
pixels[2] = (0, 0, 0)
pixels[3] = (0, 0, 255)
pixels[4] = (0, 0, 255)
pixels[5] = (0, 0, 255)
pixels[6] = (0, 0, 255)
pixels[7] = (0, 0, 0)
pixels[8] = (0, 0, 0)
pixels[9] = (0, 0, 0)
resultado = False
else:
pixels[0] = (0, 0, 0)
pixels[1] = (0, 0, 0)
pixels[2] = (0, 0, 0)
pixels[3] = (0, 0, 0)
pixels[4] = (0, 0, 0)
pixels[5] = (0, 0, 0)
pixels[6] = (0, 0, 0)
pixels[7] = (0, 0, 255)
pixels[8] = (0, 0, 255)
pixels[9] = (0, 0, 255)
resultado = True
else:
print("¡No hay riesgo detectado!")
for i in range(3):
pixels.fill(GREEN)
pixels.show()
time.sleep(0.05)
pixels.fill(PIXELS_OFF)
pixels.show()
time.sleep(0.05)
except:
continue
time.sleep(0.025)

How do I use roll, pitch and yaw to fuse in with my 3-D points points to make a 3-D surface?

I have a array of 3-D points in a way like that each 24 set of 3-D points are on a same plane and they form roughly a circle. I am trying to add the data of roll, pitch and yaw to the dataset such that each 24 set of point after applying the rotation angles about the axis formulates the circle in such a way that it appears to be in a tube form which is bending. The code that I am using formulates this into a surface using OpenGL. Data collected is from a IMU travelled inside a pipe.
The problem I am facing is as I apply this data to create this tube diagrammed, until rotation along Z-axis(which is roll) everything seems to be fine but when I multiply the rotation matrix along x and y axis the output is skewed and completely wrong. Can anyone point what I am doing wrong in my code
This is the code I have made for rotation
import numpy as np
roll = np.load("tube_roll.npy")
pitch = np.load("tube_pitch.npy")
yaw = np.load("tube_yaw.npy")
data = np.load("three_d.npy")
def matrix_angle(angle, a, b, c, d, e):
cos = np.cos(angle)
sin = np.sin(angle)
zer = np.zeros((angle.shape[0], 3,3))
zer[:, a[0], a[1]] = 1
zer[:, b[0], b[1]] = cos
zer[:, c[0], c[1]] = -sin
zer[:, d[0], d[1]] = sin
zer[:, e[0], e[1]] = cos
return zer
rot_along_x = matrix_angle(yaw, [0, 0], [1, 1], [1, 2], [2, 1], [2, 2])
rot_along_y = matrix_angle(pitch, [1, 1], [0, 0], [2, 0], [0, 2], [2, 2])
rot_along_z = matrix_angle(roll, [2, 2], [0, 0], [0, 1], [1, 0], [1, 1])
a = []
for j in range(0, len(rot_along_z)):
b = []
for i in range(0, 24):
dd = np.dot(rot_along_z[j], data[j, i, :])
dd = np.dot(rot_along_y[j], dd)
dd = np.dot(rot_along_x[j], dd)
b.append(dd)
a.append(b)
a = np.array(a)
np.save("three_data.npy", a)
And this is what I am using for making the 3-D view.
import OpenGL.GL as gl
import OpenGL.arrays.vbo as glvbo
from PyQt5.Qt import *
import numpy as np
import math
import sys
VS = '''
attribute vec3 position;
attribute vec3 a_Color;
uniform mat4 u_proj;
uniform mat4 u_view;
uniform mat4 u_model;
out vec3 g_color;
void main() {
gl_Position = u_proj * u_view * u_model * vec4(position, 1.0);
g_color = a_Color;
}
'''
FS = '''
#version 450
in vec3 g_color;
out vec4 outColor;
void main()
{
float d = 1.0 - gl_FragCoord.z;
outColor = vec4(g_color * d, 1.0);
}
'''
class CreateTubeWindow(QMainWindow):
def __init__(self, *args):
super(CreateTubeWindow, self).__init__()
self.setWindowTitle('3-D Pipeline View')
self.plot = GLPlotWidget3D(self)
self.setCentralWidget(self.plot)
[_, w] = Sb.screen_size()
self.setGeometry(w[2]/2-50, w[3]/2-50, w[2]/2-50, w[3]/2-50)
self.plot.show()
self.show()
class GLPlotWidget3D(QGLWidget):
def __init__(self, *args):
# QGLWidget.__init__(self)
super(GLPlotWidget3D, self).__init__()
self.parent_s = args[0]
self.parent_s = self.parent_s
self.width, self.height = 100, 100
self.right, self.left, self.top, self.bottom = 21000, -21000, 10, -10
self.data = np.zeros((3, 10, 2))
self.vbo = glvbo.VBO(self.data)
self.x = 0
self.y = 0
self.vxb, self.vyb = 0, 0
self.count = 0
# self.showMaximized()
# self.show()
def initializeGL(self):
vs = Sb.compile_vertex_shader(VS)
fs = Sb.compile_fragment_shader(FS)
self.shaders_program_tube = Sb.link_shader_program(vs, fs)
self.attrib = {a: gl.glGetAttribLocation(self.shaders_program_tube, a) for a in ['position', 'a_Color']}
self.uniform = {u: gl.glGetUniformLocation(self.shaders_program_tube, u) for u in
['u_model', 'u_view', 'u_proj']}
self.roll = np.load('tube_roll.npy')
self.pitch = np.load('tube_pitch.npy')
self.yaw = np.load('tube_yaw.npy')
self.e = np.load("three_data.npy")
self.e = np.array(self.e, dtype=np.float32)
self.color = np.zeros((self.e.shape[0]*self.e.shape[1], 3), dtype=np.float32)
self.color.fill(1.0)
self.elems = self.elements_array(self.e.shape[0], self.e.shape[1])
self.elems = np.array(self.elems, dtype=np.int32)
self.vertexbuffer = gl.glGenBuffers(1)
gl.glBindBuffer(gl.GL_ARRAY_BUFFER, self.vertexbuffer)
gl.glBufferData(gl.GL_ARRAY_BUFFER, self.e, gl.GL_DYNAMIC_DRAW)
self.elementbuffer = gl.glGenBuffers(1)
gl.glBindBuffer(gl.GL_ELEMENT_ARRAY_BUFFER, self.elementbuffer)
gl.glBufferData(gl.GL_ELEMENT_ARRAY_BUFFER, self.elems, gl.GL_DYNAMIC_DRAW)
self.colorbuffer = gl.glGenBuffers(1)
gl.glBindBuffer(gl.GL_ARRAY_BUFFER, self.colorbuffer)
gl.glBufferData(gl.GL_ARRAY_BUFFER, self.color, gl.GL_DYNAMIC_DRAW)
self.scaleZ = 30/self.e[:, :, 2].max()
self.right, self.left, self.top, self.bottom, self.far, self.near = self.e[:, :, 1].min(), self.e[:, :,
1].max(), self.e[:,
:,
0].min(), self.e[
:,
:,
0].max(), self.e[
:,
:,
2].max(), self.e[
:,
:,
2].min()
self.far *= self.scaleZ
self.near *= self.scaleZ
self.angle = 0.962
self.angle_y = 133.544
self.zoom = True
self.zoom_c = 90.0
self.zoom_cv = 0.0
def perspective_view(self):
# projection matrix
aspect, ta, near, far = self.width / self.height, np.tan(np.radians(self.zoom_c) / 2), 10, 50
proj = np.matrix(((1 / ta / aspect, 0, 0, 0), (0, 1 / ta, 0, 0), (0, 0, -(far + near) / (far - near), -1),
(0, 0, -2 * far * near / (far - near), 0)), np.float32)
# view matrix
view = np.matrix(((1, 0, 0, 0), (0, 0, -1, 0), (0, 1, 0, 0), (0, 0, -30, 1)), np.float32)
# model matrix
c, s = math.cos(self.angle), math.sin(self.angle)
cy, sy = math.cos(self.angle_y), math.sin(self.angle_y)
scale = np.matrix(((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, self.scaleZ, 0), (0, 0, 0, 1)), np.float32)
rotZ = np.array(((c, s, 0, 0), (-s, c, 0, 0), (0, 0, 1, 0), (0, 0, 0, 1)), np.float32)
rotY = np.matrix(((cy, 0, sy, 0), (0, 1, 0, 0), (-sy, 0, cy, 0), (0, 0, 0, 1)), np.float32)
trans = np.matrix(((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 0, (self.near - self.far) / 2, 1)), np.float32)
model = scale * trans * rotY * rotZ
gl.glUniformMatrix4fv(self.uniform['u_proj'], 1, gl.GL_FALSE, proj)
gl.glUniformMatrix4fv(self.uniform['u_view'], 1, gl.GL_FALSE, view)
gl.glUniformMatrix4fv(self.uniform['u_model'], 1, gl.GL_FALSE, model)
def paintGL(self):
self.resizeGL(self.width, self.height)
gl.glClearColor(0.2, 0.2, 0.2, 0)
gl.glClear(gl.GL_COLOR_BUFFER_BIT | gl.GL_DEPTH_BUFFER_BIT)
gl.glEnable(gl.GL_DEPTH_TEST)
gl.glUseProgram(self.shaders_program_tube)
gl.glBindBuffer(gl.GL_ARRAY_BUFFER, self.vertexbuffer)
stride = 0 # 3*self.e.itemsize
offset = None # ctypes.c_void_p(0)
loc = self.attrib['position']
gl.glEnableVertexAttribArray(loc)
gl.glVertexAttribPointer(loc, 3, gl.GL_FLOAT, False, stride, offset)
gl.glBindBuffer(gl.GL_ELEMENT_ARRAY_BUFFER, self.elementbuffer)
self.perspective_view()
loc = self.attrib['a_Color']
gl.glEnableVertexAttribArray(loc)
gl.glBindBuffer(gl.GL_ARRAY_BUFFER, self.colorbuffer)
gl.glVertexAttribPointer(loc, 3, gl.GL_FLOAT, False, stride, offset)
gl.glDrawElements(gl.GL_TRIANGLE_STRIP, self.elems.size, gl.GL_UNSIGNED_INT, None)
def resizeGL(self, width, height):
self.width, self.height = width, height
gl.glViewport(0, 0, width, height)
def mouseMoveEvent(self, e):
if self.zoom:
v = self.x-e.x()
if v > 2:
self.angle -= 0.01
elif v < -2:
self.angle += 0.01
self.x = e.x()
w = self.y-e.y()
if w > 2:
self.angle_y += 0.01
elif w < -2:
self.angle_y -= 0.01
self.y = e.y()
else:
if e.x() > self.zoom_cv:
self.zoom_c -= 1
else:
self.zoom_c += 1
self.zoom_cv = e.x()
self.update()
def keyPressEvent(self, k):
if k.key() == 16777249:
self.zoom = False
def keyReleaseEvent(self, k):
if k.key() == 16777249:
self.zoom = True
def wheelEvent(self, w):
e = w.angleDelta().y()
if e > 0:
self.zoom_c -= 1
else:
self.zoom_c += 1
self.update()
def elements_array(self, a, b):
ring_c = b
slice_c = a
my_si = np.arange(slice_c - 1)
my_elems = np.repeat(ring_c * my_si, 2)
temp = np.empty(2 * my_si.size, my_si.dtype)
temp[0::2] = my_si
temp[1::2] = my_si + 1
my_ri = np.arange(ring_c + 1)
my_ie = np.expand_dims(my_ri % ring_c, axis=1)
my_si = temp * ring_c + my_ie
my_elems = np.vstack((my_elems, my_si))
N = my_elems.shape[1] // (slice_c - 1)
return my_elems.reshape((my_elems.shape[0], -1, N)).swapaxes(0, 1).reshape(
(np.prod(my_elems.shape), -1)).squeeze()
if __name__ == '__main__':
app = QApplication(sys.argv)
editor = CreateTubeWindow()
sys.exit(app.exec_())
What I feel is I am doing something wrong with my rotation matrix as the output of rotation along Z-axis seems wrong as it's initially in a sort of 2-D plane but as we go further matrix multiplication increased the value of x and y coordinate also which should not happen.
Also below are the data file used
https://drive.google.com/file/d/177knYTSmlWcC1RQjcXf-CKICWr09MU_i/view?usp=sharing
Either use numpy.matmul for matrix multiplications:
rot_mat = np.matmul(rot_along_x, np.matmul(rot_along_y, rot_along_z))
or use the matrix multiplication (#) operator (see array ):
rot_mat = rot_along_z # rot_along_y # rot_along_x
Use numpy.dot to transform the vertices:
a = np.array([[np.dot(v, rot_mat) for v in row] for row in data])

How does PyOpenGL pick the colors to draw each shape?

I am in the middle of a PyQt5 PyOpenGL project. I am trying to draw a white wireframe cube with a bunch of colored solid cubes. Wireframe cubes are drawn from a list of tuple points, and a list of tuple references to those points. Solid cubes are drawn from a list of tuple references to the points. Here is the cube code:
class cube():
render = True
solid = False
color = (1, 1, 1)
def config(self, x, y, z, size = 0.1, solid = False, color = (1, 1, 1)):
self.solid = solid
self.color = color
self.size = size / 2
s = self.size
self.vertices = [
(-s + x, s + y, -s + z),
(s + x, s + y, -s + z),
(s + x, -s + y, -s + z),
(-s + x, -s + y, -s + z),
(-s + x, s + y, s + z),
(s + x, s + y, s + z),
(s + x, -s + y, s + z),
(-s + x, -s + y, s + z)
]
self.edges = [
(0,1), (0,3), (0,4), (2,1),
(2,3), (2,6), (7,3), (7,4),
(7,6), (5,1), (5,4), (5,6)
]
self.facets = [
(0, 1, 2, 3), (0, 1, 6, 5),
(0, 3, 7, 4), (6, 5, 1, 2),
(6, 7, 4, 5), (6, 7, 3, 2)
]
def show(self):
self.render = True
def hide(self):
self.render = False
To render a cube, I get the size of a list held in my mainWindow class, then append an instance of the cube class to that list. I can then reference that instance by using the size before appending. Here is the code for the render function:
def paintGL(self):
glLoadIdentity()
gluPerspective(45, self.width / self.height, 0.1, 110.0) #set perspective?
glTranslatef(0, 0, self.zoomLevel) #I used -10 instead of -2 in the PyGame version.
glRotatef(self.rotateDegreeV, 1, 0, 0) #I used 2 instead of 1 in the PyGame version.
glRotatef(self.rotateDegreeH, 0, 0, 1)
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)
if len(self.shapes) != 0:
glBegin(GL_LINES)
for s in self.shapes:
if s.render and not s.solid:
for e in s.edges:
for v in e:
glVertex3fv(s.vertices[v])
glEnd()
glBegin(GL_QUADS)
for s in self.shapes:
if s.render and s.solid:
for f in s.facets:
for v in f:
glColor3fv(s.color)
glVertex3fv(s.vertices[v])
glEnd()
If I render just one cube in wireframe, it renders white. If I add a red solid cube and a blue solid cube after it, the wireframe cube is colored in the last color used, whatever it may be. For example:
self.shapes.append(self.cube())
self.shapes.append(self.cube())
self.shapes.append(self.cube())
self.shapes[0].config(-1, 0, 0, size = 0.5, solid = False)
self.shapes[1].config(0, 0, 0, size = 0.5, solid = True, color = (1, 0, 0))
self.shapes[2].config(1, 0, 0, size = 0.5, solid = True, color = (0, 0, 1))
Result:
How can I make my wireframes render in the default white or a different color? I would expect glClear() would reset it and draw the wireframe in white, given that it is the first one.
Here is the full code:
import sys
from PyQt5.QtWidgets import (
QApplication, QMainWindow, QSlider,
QOpenGLWidget, QLabel, QPushButton
)
from PyQt5.QtCore import Qt
from OpenGL.GL import (
glLoadIdentity, glTranslatef, glRotatef,
glClear, glBegin, glEnd,
glColor3fv, glVertex3fv,
GL_COLOR_BUFFER_BIT, GL_DEPTH_BUFFER_BIT,
GL_QUADS, GL_LINES
)
from OpenGL.GLU import gluPerspective
class mainWindow(QMainWindow): #Main class.
shapes = [] #this will hold instances of the following classes:
zoomLevel = -10
rotateDegreeV = -90
rotateDegreeH = 0
class cube():
render = True
solid = False
color = (1, 1, 1)
def config(self, x, y, z, size = 0.1, solid = False, color = (1, 1, 1)):
self.solid = solid
self.color = color
self.size = size
s = self.size / 2
self.vertices = [
(-s + x, s + y, -s + z),
(s + x, s + y, -s + z),
(s + x, -s + y, -s + z),
(-s + x, -s + y, -s + z),
(-s + x, s + y, s + z),
(s + x, s + y, s + z),
(s + x, -s + y, s + z),
(-s + x, -s + y, s + z)
]
self.edges = [
(0,1), (0,3), (0,4), (2,1),
(2,3), (2,6), (7,3), (7,4),
(7,6), (5,1), (5,4), (5,6)
]
self.facets = [
(0, 1, 2, 3), (0, 1, 6, 5),
(0, 3, 7, 4), (6, 5, 1, 2),
(6, 7, 4, 5), (6, 7, 3, 2)
]
def show(self):
self.render = True
def hide(self):
self.render = False
def keyPressEvent(self, event): #This is the keypress detector. I use this to determine input to edit grids.
try:
key = event.key()
if key == 87:
self.rotateV(5)
elif key == 65:
self.rotateH(5)
elif key == 83:
self.rotateV(-5)
elif key == 68:
self.rotateH(-5)
elif key == 67:
self.zoom(1)
elif key == 88:
self.zoom(-1)
except:
pass
def __init__(self):
super(mainWindow, self).__init__()
self.width = 700 #Variables used for the setting of the size of everything
self.height = 600
self.setGeometry(0, 0, self.width, self.height) #Set the window size
self.shapes.append(self.cube())
self.shapes.append(self.cube())
self.shapes.append(self.cube())
self.shapes[0].config(-1, 0, 0, size = 0.5, solid = False)
self.shapes[1].config(0, 0, 0, size = 0.5, solid = True, color = (1, 0, 0))
self.shapes[2].config(1, 0, 0, size = 0.5, solid = True, color = (0, 0, 1))
def setupUI(self):
self.openGLWidget = QOpenGLWidget(self) #Create the GLWidget
self.openGLWidget.setGeometry(0, 0, self.width, self.height) #Size it the same as the window.
self.openGLWidget.initializeGL()
self.openGLWidget.resizeGL(self.width, self.height) #Resize GL's knowledge of the window to match the physical size?
self.openGLWidget.paintGL = self.paintGL #override the default function with my own?
def zoom(self, value):
self.zoomLevel += value
self.openGLWidget.update()
def rotateV(self, value):
self.rotateDegreeV += value
self.openGLWidget.update()
def rotateH(self, value):
self.rotateDegreeH += value
self.openGLWidget.update()
def paintGL(self):
glLoadIdentity()
gluPerspective(45, self.width / self.height, 0.1, 110.0) #set perspective?
glTranslatef(0, 0, self.zoomLevel) #I used -10 instead of -2 in the PyGame version.
glRotatef(self.rotateDegreeV, 1, 0, 0) #I used 2 instead of 1 in the PyGame version.
glRotatef(self.rotateDegreeH, 0, 0, 1)
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)
if len(self.shapes) != 0:
glBegin(GL_LINES)
for s in self.shapes:
if s.render and not s.solid:
for e in s.edges:
for v in e:
glVertex3fv(s.vertices[v])
glEnd()
glBegin(GL_QUADS)
for s in self.shapes:
if s.render and s.solid:
for f in s.facets:
for v in f:
glColor3fv(s.color)
glVertex3fv(s.vertices[v])
glEnd()
app = QApplication([])
window = mainWindow()
window.setupUI()
window.show()
sys.exit(app.exec_())
OpenGL is a state engine. Once a state is set, it is kept until it is changed again, even beyond frames. The current color is a global state. When glColor* is called, then the current color is set.
When glVertex* is called, then the current color, normal and texture coordinates are associated with the vertex.
That means, the proper color has to be set before the vertices are specified. You missed to set the color attribute, before you draw the wireframe cube:
class mainWindow(QMainWindow): #Main class.
# [...]
def paintGL(self):
# [...]
if len(self.shapes) != 0:
glBegin(GL_LINES)
for s in self.shapes:
glColor3fv(s.color) # <------------------------
if s.render and not s.solid:
for e in s.edges:
for v in e:
glVertex3fv(s.vertices[v])
glEnd()
glBegin(GL_QUADS)
for s in self.shapes:
glColor3fv(s.color)
if s.render and s.solid:
for f in s.facets:
for v in f:
glVertex3fv(s.vertices[v])
glEnd()
Note, it is not necessary to set the current color before each call to glVertex3fv. It is sufficient to set the current color once, when it is changed. The new color is associated to all the following vertices.

Color doesn't apply as expected with glDrawArrays (Pyglet)

If I draw rectangles with the following code:
def render(shape):
gl.glLoadIdentity()
gl.glVertexPointer(2, gl.GL_FLOAT, 0, 0)
gl.glBindBuffer(gl.GL_ARRAY_BUFFER, shape.vbo_id)
gl.glColor4ub(shape.color[0], shape.color[1], shape.color[2], 255)
gl.glDrawArrays(shape.draw_mode, 0, shape.size)
...The colors I get are one off. If I draw Red, Green, Blue, Violet squares, I actually get Green, Blue, Violet, Red.
If I swap the color and draw lines like this:
def render(shape):
gl.glLoadIdentity()
gl.glVertexPointer(2, gl.GL_FLOAT, 0, 0)
gl.glBindBuffer(gl.GL_ARRAY_BUFFER, shape.vbo_id)
# SWAPPED
gl.glDrawArrays(shape.draw_mode, 0, shape.size)
gl.glColor4ub(shape.color[0], shape.color[1], shape.color[2], 255)
Then all but the last will draw the colors correctly. The last defaults to white. UNLESS I draw over and over in a loop. Then it is ok.
What is happening? I'm not great at OpenGL and I'm not sure where to look.
Full example:
import pyglet
import ctypes
import pyglet.gl as gl
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)
VIOLET = (255, 0, 255)
def start_render():
gl.glClear(gl.GL_COLOR_BUFFER_BIT | gl.GL_DEPTH_BUFFER_BIT)
gl.glMatrixMode(gl.GL_MODELVIEW)
gl.glEnableClientState(gl.GL_VERTEX_ARRAY)
def set_viewport(left, right, bottom, top):
# gl.glViewport(0, 0, _window.height, _window.height)
gl.glMatrixMode(gl.GL_PROJECTION)
gl.glLoadIdentity()
gl.glOrtho(left, right, bottom, top, -1, 1)
gl.glMatrixMode(gl.GL_MODELVIEW)
gl.glLoadIdentity()
def open_window(width, height, window_title):
window = pyglet.window.Window(width=width, height=height,
caption=window_title)
set_viewport(0, width - 1, 0, height - 1)
window.invalid = False
return window
class VertexBuffer:
def __init__(self, vbo_id: gl.GLuint, size: float, draw_mode: int):
self.vbo_id = vbo_id
self.size = size
self.draw_mode = draw_mode
self.color = None
self.line_width = 0
def create_rectangle(center_x, center_y, width, height, color):
x1 = -width / 2 + center_x
y1 = -height / 2 + center_y
x2 = width / 2 + center_x
y2 = -height / 2 + center_y
x3 = width / 2 + center_x
y3 = height / 2 + center_y
x4 = -width / 2 + center_x
y4 = height / 2 + center_y
data = [x1, y1,
x2, y2,
x3, y3,
x4, y4]
# print(data)
vbo_id = gl.GLuint()
gl.glGenBuffers(1, ctypes.pointer(vbo_id))
# Create a buffer with the data
# This line of code is a bit strange.
# (gl.GLfloat * len(data)) creates an array of GLfloats, one for each number
# (*data) initalizes the list with the floats. *data turns the list into a
# tuple.
data2 = (gl.GLfloat * len(data))(*data)
gl.glBindBuffer(gl.GL_ARRAY_BUFFER, vbo_id)
gl.glBufferData(gl.GL_ARRAY_BUFFER, ctypes.sizeof(data2), data2,
gl.GL_STATIC_DRAW)
shape_mode = gl.GL_QUADS
shape = VertexBuffer(vbo_id, len(data) // 2, shape_mode)
shape.color = color
return shape
def render(shape):
gl.glLoadIdentity()
gl.glVertexPointer(2, gl.GL_FLOAT, 0, 0)
gl.glBindBuffer(gl.GL_ARRAY_BUFFER, shape.vbo_id)
gl.glColor4ub(shape.color[0], shape.color[1], shape.color[2], 255)
gl.glDrawArrays(shape.draw_mode, 0, shape.size)
class MyApp:
def __init__(self):
self.r1 = None
self.r2 = None
self.r3 = None
self.r4 = None
self.window = None
def setup(self):
self.window = open_window(800, 600, "Test 2")
self.r1 = create_rectangle(100, 100, 50, 50, RED) # Green
self.r2 = create_rectangle(200, 200, 50, 50, GREEN) # Blue
self.r3 = create_rectangle(300, 300, 50, 50, BLUE) # Violet
self.r4 = create_rectangle(400, 400, 50, 50, VIOLET) # Red
pyglet.clock.schedule_interval(self.draw, 1/60)
def draw(self, dt):
start_render()
render(self.r1)
render(self.r2)
render(self.r3)
render(self.r4)
def main1():
# This just draws one frame and stops.
window = open_window(800, 600, "Test 1")
r1 = create_rectangle(100, 100, 50, 50, RED)
r2 = create_rectangle(200, 200, 50, 50, GREEN)
r3 = create_rectangle(300, 300, 50, 50, BLUE)
r4 = create_rectangle(400, 400, 50, 50, VIOLET)
start_render()
render(r1)
render(r2)
render(r3)
render(r4)
window.flip()
pyglet.app.run()
def main2():
# This main function repeatedly updates the screen.
app = MyApp()
app.setup()
pyglet.app.run()
main1()
gl.glVertexPointer(2, gl.GL_FLOAT, 0, 0)
^ what VBO is bound?
gl.glBindBuffer(gl.GL_ARRAY_BUFFER, shape.vbo_id)
Wrong order. Right now glVertexPointer() is using whatever buffer you happened to have bound.
Bind then Pointer:
gl.glBindBuffer(gl.GL_ARRAY_BUFFER, shape.vbo_id)
gl.glVertexPointer(2, gl.GL_FLOAT, 0, 0)

Snake game in Python using Turtle graphics

So I've been working on a few games in Python (battleships, tic-tac-toe etc.) and this week's project is Snake. I've got a basic set-up going; the snake can move and eats the food but I haven't programmed in collision detection or going off the edge yet. The problem is response time. If you run the code below, you'll see that the snake responds to key presses, but not for a couple of - I'll call them frames - after the press. I don't quite understand how the listen() method works; am I using it properly? If not, how should I use it, and if so, how can I fix the delay? I know about Pygame, but a) I can't find an easy to install 64 bit version for python 3.4 (this one http://www.lfd.uci.edu/~gohlke/pythonlibs/#pygame is not easy to install, what the heck is a whl file?) and b) I want to challenge myself anyway.
Any help would be appreciated.
import random
import turtle
import time
class Square:
def __init__(self, x, y):
self.x = x
self.y = y
def drawself(self, turtle):
# draw a black box at its coordinates, leaving a small gap between cubes
turtle.goto(self.x - 9, self.y - 9)
turtle.begin_fill()
for i in range(4):
turtle.forward(18)
turtle.left(90)
turtle.end_fill()
class Food:
def __init__(self, x, y):
self.x = x
self.y = y
self.state = "ON"
def changelocation(self):
# I haven't programmed it to spawn outside the snake's body yet
self.x = random.randint(0, 20)*20 - 200
self.y = random.randint(0, 20)*20 - 200
def drawself(self, turtle):
# similar to the Square drawself, but blinks on and off
if self.state == "ON":
turtle.goto(self.x - 9, self.y - 9)
turtle.begin_fill()
for i in range(4):
turtle.forward(18)
turtle.left(90)
turtle.end_fill()
def changestate(self):
# controls the blinking
self.state = "OFF" if self.state == "ON" else "ON"
class Snake:
def __init__(self):
self.headposition = [20, 0] # keeps track of where it needs to go next
self.body = [Square(-20, 0), Square(0, 0), Square(20, 0)] # body is a list of squares
self.nextX = 1 # tells the snake which way it's going next
self.nextY = 0
self.crashed = False # I'll use this when I get around to collision detection
self.nextposition = [self.headposition[0] + 20*self.nextX,
self.headposition[1] + 20*self.nextY]
# prepares the next location to add to the snake
def moveOneStep(self):
if Square(self.nextposition[0], self.nextposition[1]) not in self.body:
# attempt (unsuccessful) at collision detection
self.body.append(Square(self.nextposition[0], self.nextposition[1]))
# moves the snake head to the next spot, deleting the tail
del self.body[0]
self.headposition[0], self.headposition[1] = self.body[-1].x, self.body[-1].y
# resets the head and nextposition
self.nextposition = [self.headposition[0] + 20*self.nextX,
self.headposition[1] + 20*self.nextY]
else:
self.crashed = True # more unsuccessful collision detection
def moveup(self): # pretty obvious what these do
self.nextX = 0
self.nextY = 1
def moveleft(self):
self.nextX = -1
self.nextY = 0
def moveright(self):
self.nextX = 1
self.nextY = 0
def movedown(self):
self.nextX = 0
self.nextY = -1
def eatFood(self):
# adds the next spot without deleting the tail, extending the snake by 1
self.body.append(Square(self.nextposition[0], self.nextposition[1]))
self.headposition[0], self.headposition[1] = self.body[-1].x, self.body[-1].y
self.nextposition = [self.headposition[0] + 20*self.nextX,
self.headposition[1] + 20*self.nextY]
def drawself(self, turtle): # draws the whole snake when called
for segment in self.body:
segment.drawself(turtle)
class Game:
def __init__(self):
# game object has a screen, a turtle, a basic snake and a food
self.screen = turtle.Screen()
self.artist = turtle.Turtle()
self.artist.up()
self.artist.hideturtle()
self.snake = Snake()
self.food = Food(100, 0)
self.counter = 0 # this will be used later
self.commandpending = False # as will this
def nextFrame(self):
while True: # now here's where it gets fiddly...
game.screen.listen()
game.screen.onkey(game.snakedown, "Down")
game.screen.onkey(game.snakeup, "Up")
game.screen.onkey(game.snakeleft, "Left")
game.screen.onkey(game.snakeright, "Right")
turtle.tracer(0) # follow it so far?
self.artist.clear()
if self.counter == 5:
# only moves to next frame every 5 loops, this was an attempt to get rid of the turning delay
if (self.snake.nextposition[0], self.snake.nextposition[1]) == (self.food.x, self.food.y):
self.snake.eatFood()
self.food.changelocation()
else:
self.snake.moveOneStep()
self.counter = 0
else:
self.counter += 1
self.food.changestate() # makes the food flash
self.food.drawself(self.artist) # show the food and snake
self.snake.drawself(self.artist)
turtle.update()
self.commandpending = False
time.sleep(0.05)
def snakeup(self):
print("going up") # put this in for debugging purposes
if not self.commandpending:
# should allow only one turn each frame; I don't think it's working
self.snake.moveup()
self.commandpending = True
def snakedown(self):
print("going down")
if not self.commandpending:
self.snake.movedown()
self.commandpending = True
def snakeleft(self):
print("going left")
if not self.commandpending:
self.snake.moveleft()
self.commandpending = True
def snakeright(self):
print("going right")
if not self.commandpending:
self.snake.moveright()
self.commandpending = True
game = Game()
game.nextFrame()
print("game over!")
game.screen.mainloop()
Whenever you use while True: (sans break) in turtle code, you're defeating the event hander. You should instead use an ontimer() event to run your code compatibly with the event handler. Below is my rewrite of your code to do this along with some other functional and style tweaks:
from turtle import Turtle, Screen
import random
import time
SIZE = 20
class Square:
def __init__(self, x, y):
self.x = x
self.y = y
def drawself(self, turtle):
""" draw a black box at its coordinates, leaving a small gap between cubes """
turtle.goto(self.x - SIZE // 2 - 1, self.y - SIZE // 2 - 1)
turtle.begin_fill()
for _ in range(4):
turtle.forward(SIZE - SIZE // 10)
turtle.left(90)
turtle.end_fill()
class Food:
def __init__(self, x, y):
self.x = x
self.y = y
self.is_blinking = True
def changelocation(self):
# I haven't programmed it to spawn outside the snake's body yet
self.x = random.randint(0, SIZE) * SIZE - 200
self.y = random.randint(0, SIZE) * SIZE - 200
def drawself(self, turtle):
# similar to the Square drawself, but blinks on and off
if self.is_blinking:
turtle.goto(self.x - SIZE // 2 - 1, self.y - SIZE // 2 - 1)
turtle.begin_fill()
for _ in range(4):
turtle.forward(SIZE - SIZE // 10)
turtle.left(90)
turtle.end_fill()
def changestate(self):
# controls the blinking
self.is_blinking = not self.is_blinking
class Snake:
def __init__(self):
self.headposition = [SIZE, 0] # keeps track of where it needs to go next
self.body = [Square(-SIZE, 0), Square(0, 0), Square(SIZE, 0)] # body is a list of squares
self.nextX = 1 # tells the snake which way it's going next
self.nextY = 0
self.crashed = False # I'll use this when I get around to collision detection
self.nextposition = [self.headposition[0] + SIZE * self.nextX, self.headposition[1] + SIZE * self.nextY]
# prepares the next location to add to the snake
def moveOneStep(self):
if Square(self.nextposition[0], self.nextposition[1]) not in self.body:
# attempt (unsuccessful) at collision detection
self.body.append(Square(self.nextposition[0], self.nextposition[1]))
# moves the snake head to the next spot, deleting the tail
del self.body[0]
self.headposition[0], self.headposition[1] = self.body[-1].x, self.body[-1].y
# resets the head and nextposition
self.nextposition = [self.headposition[0] + SIZE * self.nextX, self.headposition[1] + SIZE * self.nextY]
else:
self.crashed = True # more unsuccessful collision detection
def moveup(self): # pretty obvious what these do
self.nextX, self.nextY = 0, 1
def moveleft(self):
self.nextX, self.nextY = -1, 0
def moveright(self):
self.nextX, self.nextY = 1, 0
def movedown(self):
self.nextX, self.nextY = 0, -1
def eatFood(self):
# adds the next spot without deleting the tail, extending the snake by 1
self.body.append(Square(self.nextposition[0], self.nextposition[1]))
self.headposition[0], self.headposition[1] = self.body[-1].x, self.body[-1].y
self.nextposition = [self.headposition[0] + SIZE * self.nextX, self.headposition[1] + SIZE * self.nextY]
def drawself(self, turtle): # draws the whole snake when called
for segment in self.body:
segment.drawself(turtle)
class Game:
def __init__(self):
# game object has a screen, a turtle, a basic snake and a food
self.screen = Screen()
self.artist = Turtle(visible=False)
self.artist.up()
self.artist.speed("slowest")
self.snake = Snake()
self.food = Food(100, 0)
self.counter = 0 # this will be used later
self.commandpending = False # as will this
self.screen.tracer(0) # follow it so far?
self.screen.listen()
self.screen.onkey(self.snakedown, "Down")
self.screen.onkey(self.snakeup, "Up")
self.screen.onkey(self.snakeleft, "Left")
self.screen.onkey(self.snakeright, "Right")
def nextFrame(self):
self.artist.clear()
if (self.snake.nextposition[0], self.snake.nextposition[1]) == (self.food.x, self.food.y):
self.snake.eatFood()
self.food.changelocation()
else:
self.snake.moveOneStep()
if self.counter == 10:
self.food.changestate() # makes the food flash slowly
self.counter = 0
else:
self.counter += 1
self.food.drawself(self.artist) # show the food and snake
self.snake.drawself(self.artist)
self.screen.update()
self.screen.ontimer(lambda: self.nextFrame(), 100)
def snakeup(self):
if not self.commandpending:
self.commandpending = True
self.snake.moveup()
self.commandpending = False
def snakedown(self):
if not self.commandpending:
self.commandpending = True
self.snake.movedown()
self.commandpending = False
def snakeleft(self):
if not self.commandpending:
self.commandpending = True
self.snake.moveleft()
self.commandpending = False
def snakeright(self):
if not self.commandpending:
self.commandpending = True
self.snake.moveright()
self.commandpending = False
game = Game()
screen = Screen()
screen.ontimer(lambda: game.nextFrame(), 100)
screen.mainloop()
Does this provide the kind of response for which you're looking?
It probably is a challenge to make a speedy game this way (but that's not all bad). I think that listen() should go after the onkey()s.
You should also look at getting rid of all the duplicated code. It might seem easy short term to just copy/paste then alter. But if you have to make major changes (like after asking on a forum) it will be tedious and error prone to alter.
PS (EDIT) also your Snake.moveOneStep() method makes a new instance of Square just to check for self collision, this seems extravagant for the sake of elegance. Better to just keep a list of locations that python (ho, ho) can check through. (Quite apart from this probably not working. Try print(Square(1,2) in [Square(1,2)]))
def check_self_collision(self, x, y):
for s in self.body:
if s.x == x and s.y == y:
return False
return True
def moveOneStep(self):
if self.check_self_collision(self.nextposition[0], self.nextposition[1]):
# attempt (unsuccessful) at collision detection
self.body.append(Square(self.nextposition[0], self.nextposition[1]))
My version:
#coding: utf-8
from Tkinter import *
import random
import time
class Levely:
def __init__(self):
self.urovne=[
[[0, 0, 0, 0, 0, 1, 1, 1, 1, 1], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 1, 1, 1, 1, 1, 0, 0, 0, 0], [0, 0, 0, 0, 0, 1, 0, 1, 1, 0], [0, 0, 0, 0, 0, 0, 0, 1, 0, 0], [0, 0, 0, 0, 0, 0, 1, 1, 0, 0], [0, 0, 1, 1, 1, 0, 0, 0, 0, 0], [0, 0, 0, 0, 1, 1, 1, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 1, 1, 1, 1]],
[[0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [0, 1, 1, 1, 0, 1, 1, 1, 0, 1], [0, 0, 0, 0, 0, 0, 1, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 1, 1, 1, 0, 0, 1, 0, 0, 0], [1, 1, 1, 0, 0, 0, 1, 0, 0, 0], [0, 0, 1, 0, 0, 0, 1, 1, 0, 1], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]],
[[0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 1, 1, 0, 0, 0, 0, 0, 0, 0], [0, 0, 1, 0, 1, 1, 1, 1, 0, 1], [0, 0, 1, 0, 0, 0, 1, 0, 0, 1], [0, 0, 0, 0, 0, 0, 1, 0, 0, 0], [0, 0, 1, 0, 0, 0, 1, 0, 0, 0], [0, 0, 1, 1, 0, 0, 0, 0, 1, 0], [0, 0, 0, 1, 1, 0, 0, 1, 0, 0], [0, 0, 0, 0, 0, 0, 0, 1, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]],
[[0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [0, 1, 1, 0, 0, 0, 0, 0, 0, 1], [0, 0, 1, 0, 0, 0, 0, 0, 1, 1], [0, 0, 1, 0, 0, 0, 1, 0, 0, 0], [0, 0, 0, 0, 0, 1, 1, 0, 0, 0], [0, 0, 0, 0, 0, 0, 1, 0, 0, 1], [0, 0, 0, 1, 0, 0, 1, 0, 0, 1], [0, 0, 0, 1, 0, 0, 0, 0, 0, 0], [0, 0, 0, 1, 0, 0, 0, 1, 1, 0], [0, 0, 1, 1, 1, 0, 0, 0, 0, 0]],
]
self.data=[[400,13],[400,10],[400,13],[400,13],[400,13],[400,13]]
print "Choose from", len(self.urovne), "levels"
self.vyber=input("Level: ")
self.vyber-=1
h=Had(self)
class Had:
def __init__(self,Levely):
self.l=Levely
self.level=self.l.urovne[self.l.vyber]
self.mrizka=len(self.level[0])
self.velikost=self.l.data[self.l.vyber][0]
self.vtelo=100
self.r=self.l.data[self.l.vyber][1]
self.x=0
self.y=0
self.u=0
self.k=self.velikost
self.c=(self.velikost/self.mrizka)
self.poprve=0
self.neco=[[0,0],0,0,0]
self.ukonceni=None
self.aakce1=None
self.aakce2=None
self.aakce3=None
self.aakce4=None
self.s=[0,0,0,0]
self.j=[]
self.konec=0
self.score=0
self.pocet_zelenych=0
self.okno=Tk()
self.platno=Canvas(self.okno,width=self.velikost,height=self.velikost,bg="white")
self.platno.pack()
self.tl=Button(self.okno, text="Restart", command=self.start)
self.tl.pack(fill=BOTH)
self.start()
self.okno.bind("<Key-d>", self.akce1)
self.okno.bind("<Key-w>", self.akce2)
self.okno.bind("<Key-s>", self.akce3)
self.okno.bind("<Key-a>", self.akce4)
self.okno.bind("<Key-r>", self.start1)
def akce1(self, klik):
self.akce11()
def akce2(self, klik):
self.akce21()
def akce3(self, klik):
self.akce31()
def akce4(self, klik):
self.akce41()
def start1(self, klik):
self.start()
def akce11(self):
if int(self.s[1])%self.c!=0:
self.aakce1=self.okno.after(9,self.akce11)
if int(self.s[1])%self.c==0:
self.x=self.c
self.y=0
self.u=0
if self.poprve==1:
self.okno.after_cancel(self.aakce1)
self.stop()
self.pohyb()
def akce21(self):
if int(self.s[0])%self.c!=0:
self.aakce1=self.okno.after(9,self.akce21)
if int(self.s[0])%self.c==0:
self.x=0
self.y=-self.c
self.u=0
if self.poprve==1:
self.okno.after_cancel(self.aakce2)
self.stop()
self.pohyb()
def akce31(self):
if int(self.s[0])%self.c!=0:
self.aakce1=self.okno.after(9,self.akce31)
if int(self.s[0])%self.c==0:
self.x=0
self.y=self.c
self.u=1
if self.poprve==1:
self.okno.after_cancel(self.aakce3)
self.stop()
self.pohyb()
def akce41(self):
if int(self.s[1])%self.c!=0:
self.aakce1=self.okno.after(9,self.akce41)
if int(self.s[1])%self.c==0:
self.x=-self.c
self.y=0
self.u=0
if self.poprve==1:
self.okno.after_cancel(self.aakce4)
self.stop()
self.pohyb()
def pohyb(self):
self.smrt()
if self.konec==1:
return None
self.test()
s=self.platno.coords(self.hlava)
self.s=self.platno.coords(self.hlava)
self.platno.delete(ALL)
self.hlava=self.platno.create_rectangle(s[0],s[1],s[2],s[3], fill="green4", outline="white")
self.jablko=self.platno.create_rectangle(self.j[0],self.j[1],self.j[2],self.j[3], fill="red", outline="red")
for x in range(self.mrizka):
for y in range(self.mrizka):
if self.level[x][y]==0:
continue
if self.level[x][y]==1:
#KURVVAAAAA x,y,x,y
self.block=self.platno.create_rectangle(y*self.c,(x*self.c),(y*self.c)+self.c,(x*self.c)+self.c, fill="black")
self.test()
s=self.platno.coords(self.hlava)
self.poloha.append(s)
self.delka=len(self.poloha)
if s[self.u]<=self.k:
self.dx=self.x
self.dy=self.y
self.platno.move(self.hlava,self.dx/10,self.dy/10)
s=self.platno.coords(self.hlava)
self.nahrada=self.platno.create_rectangle(s[0],s[1],s[2],s[3], fill="green4", outline="green4")
if s[self.u]>=self.k:
self.dx=0
self.dy=0
bla="Restart-Score:", int(self.score)
self.tl.config(text=bla)
for a in range(self.delka):
if 1==1:
self.ocas=self.platno.create_rectangle(self.poloha[a][0],self.poloha[a][1],self.poloha[a][2],self.poloha[a][3], fill="green2", outline="green2")
self.poloha_zeleny=self.platno.coords(self.ocas)
self.zeleny.append(self.poloha_zeleny)
self.pocet_zelenych=len(self.zeleny)
if self.pocet_zelenych>=self.delka:
del self.zeleny[0]
if self.delka>=self.vtelo:
self.neco=self.poloha[0]
del self.poloha[0]
self.s=self.platno.coords(self.hlava)
self.nahrada=self.platno.create_rectangle(s[0],s[1],s[2],s[3], fill="green4", outline="green4")
self.ukonceni=self.okno.after(self.r,self.pohyb)
def smrt(self):
s=self.platno.coords(self.hlava)
bla="Restart-Score:", int(self.score)
if self.level[int(s[1]/self.c)][int(s[0]/self.c)]==1:
self.platno.delete(self.hlava)
self.tl.config(text=bla)
self.konec=1
self.smrtak=self.platno.create_rectangle(s[0],s[1],s[2],s[3], fill="brown", outline="brown")
for b in range(len(self.zeleny)):
if s==self.zeleny[(b-1)]:
self.platno.delete(self.hlava)
self.tl.config(text=bla)
self.konec=1
self.smrtak=self.platno.create_rectangle(s[0],s[1],s[2],s[3], fill="brown", outline="brown")
def stop(self):
if self.poprve==1:
self.okno.after_cancel(self.ukonceni)
self.poprve=1
def start(self):
self.vtelo=60
self.platno.delete("all")
self.tl.config(text="Restart")
self.poloha=[]
self.zeleny=[]
self.konec=0
self.pocet_zelenych=0
self.score=0
self.poprve=0
self.dx=0
self.dy=0
if self.aakce1!=None:
self.okno.after_cancel(self.aakce1)
self.aakce1=None
if self.aakce2!=None:
self.okno.after_cancel(self.aakce2)
self.aakce2=None
if self.aakce3!=None:
self.okno.after_cancel(self.aakce3)
self.aakce3=None
if self.aakce4!=None:
self.okno.after_cancel(self.aakce4)
self.aakce4=None
for x in range(self.mrizka):
for y in range(self.mrizka):
if self.level[x][y]==0:
continue
if self.level[x][y]==1:
#KURVVAAAAA x,y,x,y
self.block=self.platno.create_rectangle(y*self.c,(x*self.c),(y*self.c)+self.c,(x*self.c)+self.c, fill="black")
self.hlava=self.platno.create_rectangle(0,0,self.c,self.c, fill="green4", outline="green4")
self.generace()
s=self.platno.coords(self.hlava)
self.dx=self.c
self.dy=self.c
def generace(self):
self.nx=random.randint(0,self.mrizka-1)
self.ny=random.randint(0,self.mrizka-1)
for x in self.zeleny:
if int(x[0]/self.c)==self.nx and int(x[1]/self.c)==self.ny:
self.generace()
if self.level[self.ny][self.nx]==1:
self.generace()
if self.level[self.ny][self.nx]!=1:
self.jablko=self.platno.create_rectangle(self.nx*self.c,self.ny*self.c,self.nx*self.c+self.c,self.ny*self.c+self.c, fill="red", outline="red")
def test(self):
s=self.platno.coords(self.hlava)
self.j=self.platno.coords(self.jablko)
if s==self.j:
self.vtelo+=5
self.score+=0.5
self.generace()
def mezery(self):
for x in range(30):
print ""
levliky=Levely()
mainloop()

Categories