The shape that appears
import bpy
import math
# Create a new empty mesh
mesh = bpy.data.meshes.new("Rhombicuboctahedron")
# Create a new object with the mesh
obj = bpy.data.objects.new("Rhombicuboctahedron", mesh)
# Add the object to the scene
bpy.context.collection.objects.link(obj)
# Create vertices for the rhombicuboctahedron
vertices = []
phi = (1 + math.sqrt(2)) / 2
for i in range(3):
for j in range(2):
x = (-1)**j * phi if i == 0 else 0
y = (-1)**j * phi if i == 1 else 0
z = (-1)**j * 1 if i == 2 else 0
vertices.append((x, y, z))
# Create faces for the rhombicuboctahedron
faces = [(0, 1, 2), (0, 2, 3), (0, 3, 4), (0, 4, 1), (1, 5, 2),
(2, 5, 3), (3, 5, 4), (4, 5, 1), (6, 1, 4), (6, 2, 1),
(6, 3, 2), (6, 4, 3), (5, 6, 7), (7, 1, 5), (7, 2, 1),
(7, 3, 2), (7, 4, 3), (7, 5, 4)]
# Add vertices and faces to the mesh
mesh.from_pydata(vertices, [], faces)
# Recalculate normals and update the mesh
mesh.update()
# Add materials to each face
mat = bpy.data.materials.new(name="Material")
mat.diffuse_color = (1, 1, 1)
for i, face in enumerate(mesh.polygons):
face.material_index = i
mesh.materials.append(mat)
# Create a text object for each face
for i, face in enumerate(mesh.polygons):
# Get the center point of the face
center = face.center
# Create a text object
text = bpy.data.curves.new(name="Text", type='FONT')
# Set the text to be the letter corresponding to the face
text.body = chr(ord('A') + i)
# Create an object with the text
text_obj = bpy.data.objects.new(name="Text", object_data=text)
# Set the location of the object to the center of the face
text_obj.location = center
# Rotate the object so it faces the camera
text_obj.rotation_euler = (math.pi / 2, 0, 0)
# Scale the object
text_obj.scale = (0.1, 0.1, 0.1)
# Add the object to the scene
bpy.context.collection.objects.link(text_obj)
I wanted a rhombicuboctahedron, which is a polyhedron with 26 faces. It has 8 triangular faces and 18 square faces.
The rhombicuboctahedron is an Archimedean solid, which means that it is a convex polyhedron that is made up of two or more types of regular polygons that meet in equal angles. The rhombicuboctahedron is one of the 13 Archimedean solids. It is a highly symmetrical solid, with 3-fold rotational symmetry around all four of its vertices.
This script doesnt appear even close, yet I cannot fault it. Is it the code or blender?
I'm trying to make the minesweeper game but I have seen this method to store a grid in a list.
how do I make a list inside a list that looks like my grid, For example:
list =
[[x,y],[x,y][x,y],[x,y][x,y],[x,y]
[x,y],[x,y][x,y],[x,y][x,y],[x,y]
[x,y],[x,y][x,y],[x,y][x,y],[x,y]]
My code now is that all the grid is in one list([] and not [][])
I'm kinda new to programming in python so I'm not good at it. Hoping to get help and to solve this as fast as possible, Thank You all!
My code:
import pygame
from pygame.math import Vector2
import random
pygame.init()
HEIGHT = 800
WIDTH = 800
tile_size = 100
screen = pygame.display.set_mode((WIDTH, HEIGHT))
clock = pygame.time.Clock()
class Grid:
def __init__(self):
self.pGrid = [Vector2(0, 0)]
for num in range(0, int(WIDTH/tile_size)):
for num2 in range(0, int(HEIGHT/tile_size)):
if(not(num == 0 and num2 == 0)):
self.pGrid.append(Vector2(num2*tile_size, num*tile_size))
def make_grid(self):
for line in range(0, int(WIDTH/tile_size)):
pygame.draw.line(screen, (255, 255, 255), (0, line*tile_size), (WIDTH, line*tile_size))
pygame.draw.line(screen, (255, 255, 255), (line * tile_size, 0), (line*tile_size, HEIGHT))
grid = Grid()
#def bomb_found():
#bomb = pygame.image.load('Images/Bomb.png')
#bomb = pygame.transform.scale(bomb, (100, 100))
bomb = pygame.image.load('Images/Bomb.png')
bomb = pygame.transform.scale(bomb, (100, 100))
run = True
while run:
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
screen.fill((175, 215, 70))
grid.make_grid()
#bomb_found()
screen.blit(bomb, grid.pGrid[20])
pygame.display.update()
clock.tick(60)
pygame.quit()
You could use list comprehensions for easily creating a nested array of successive integer values.
w, h = 3, 4
[[(i, j) for j in range(h)] for i in range(w)]
#result
[[(0, 0), (0, 1), (0, 2), (0, 3)],
[(1, 0), (1, 1), (1, 2), (1, 3)],
[(2, 0), (2, 1), (2, 2), (2, 3)]]
Create a list for the column before the inner loop and add the Vector2 objects to this list. Add the column list to the grid after the inner loop:
class Grid:
def __init__(self):
self.pGrid = []
for col in range(WIDTH//tile_size):
column = []
for row in range(HEIGHT//tile_size):
column.append(Vector2(col * tile_size, row * tile_size))
self.pGrid.append(column)
The same using List Comprehensions:
class Grid:
def __init__(self):
self.pGrid = [[Vector2(c*tile_size, r*tile_size) for r in range(HEIGHT//tile_size)] for c in range(WIDTH//tile_size)]
The first subscription returns a column and the second subscription returns an item in the column (a row in the column). e.g.:
col = 3 # 4th column
row = 2 # 3rd row
screen.blit(bomb, grid.pGrid[col][row])
I'm new to using Turtle graphics in Python 3, and I'm at a loss on what to do. One of my problems is that I have no idea where to begin with creating a function that will draw a marker inside of a grid cell based on a data set called 'path' containing 3 variables. The grid map itself is 7x7 and there's 5 markers in total (ranging from 0 to 4). Each marker draws its own social media logo and are completely different from each other.
grid_cell_size = 100 # px
num_squares = 7 # this for creating the 7x7 grid map
# for clarification: path = ['Start', location, marker_value]
path = [['Start', 'Centre', 4], ['North', 2, 3],
['East', 2, 2], ['South', 4, 1], ['West', 2, 0]]
My main goal is to be able to draw all 5 markers at once in their own location coordinates using the above data set. I'm not sure how should I approach with assigning these markers to their own marker_value. Would an if/elif/else statement work for this?
Trying to implement 5 markers at once is too overwhelming for me so I've tried using this very simple data set called 'path_var_3' that will only draw 1 marker.
path_var_3 = [['Start', 'Bottom left', 3]]
def follow_path(path_selection):
# Draws YouTube logo marker
if 3 in path_var_3[0]:
penup()
# !!!
goto(0, -32)
setheading(90)
# Variables
youtube_red = '#ff0000'
youtube_white = 'White'
radius = 10
diameter = radius * 2
# Prep to draw the superellipse
pencolor(youtube_red)
fillcolor(youtube_red)
# Drawing the superellipse
begin_fill()
pendown()
for superellipse in range(2):
circle(radius, 90)
forward(80)
circle(radius, 90)
forward(60 - diameter)
# Finish up
end_fill()
penup()
# Move turtle position towards the centre of the superellipse
# !!!
goto(-59)
backward(16)
setheading(90)
fillcolor(youtube_white)
# Drawing the white 'play icon' triangle
begin_fill()
pendown()
for play_triangle in range(2):
right(120)
forward(28)
right(120)
forward(28)
# Finish up
endfill()
penup()
else: return print('ERROR')
follow_path(path_var_3)
So far I was able to draw the marker in the program, but immediately I've encountered my first problem: I've realised that I've hardcoded the coordinates of where the superellipse and the triangle will begin to draw at, as indicated with the '!!!' comments. So when I run the program the marker is drawn outside of the grid cell. How do I get the marker to be drawn INSIDE a cell, regardless of where the cell is located within the 7x7 grid map?
If anyone has any ideas or is able to help I will greatly appreciate it.
TL;DR:
How do I draw a marker, consisting of various shapes, inside the 100x100 cell within the 7x7 grid map?
How do I draw a marker in any cell based on the location variable from a data set?
How should I approach with assigning markers to integers ranging 0-4? If/elif/else statements?
The code you provided isn't runnable due to goto(-59) and endfill() not being valid function calls. In the large, your code is lacking a layer to organize the problem you're trying to solve. (E.g. you need to define code-wise what 'Bottom left' or 'East' mean.) In the small, your YouTube logo drawing is using absolute coordinates instead of relative, preventing it from being drawn anywhere.
Below is a skeletal implementation of what you describe. It draws a grid for debugging purposes to show that logos are ending up in the correct locations. It substitutes colored circles for all but the YouTube logo:
from turtle import Turtle, Screen
path = [('Start', 'Centre', 4), ('North', 2, 3), ('East', 2, 2), ('South', 4, 1), ('West', 2, 0)]
GRID_CELL_SIZE = 100 # pixels
NUMBER_SQUARES = 7 # this for creating the 7x7 grid map
ABSOLUTE_OFFSETS = {
'Centre': (NUMBER_SQUARES // 2, NUMBER_SQUARES // 2),
'Bottom left': (0, NUMBER_SQUARES - 1),
# etc.
}
COMPASS_OFFSETS = {
'North': (0, 1),
'East': (1, 0),
'South': (0, -1),
'West': (-1, 0),
'Start': (1, 1), # Special case, assumes absolute offset
}
# YouTube Variables
YOUTUBE_RED = '#ff0000'
YOUTUBE_WHITE = 'White'
YOUTUBE_RADIUS = 10
YOUTUBE_WIDTH = 80
YOUTUBE_HEIGHT = 60
YOUTUBE_TRIANGLE_EDGE = 28
def draw_grid(): # for debugging
grid = Turtle(visible=False)
grid.speed('fastest')
grid.dot() # visualize origin
grid.penup()
grid.goto(-GRID_CELL_SIZE * NUMBER_SQUARES / 2, GRID_CELL_SIZE * (NUMBER_SQUARES / 2 - 1))
for _ in range(NUMBER_SQUARES - 1):
grid.pendown()
grid.forward(NUMBER_SQUARES * GRID_CELL_SIZE)
grid.penup()
grid.goto(-GRID_CELL_SIZE * NUMBER_SQUARES / 2, grid.ycor() - GRID_CELL_SIZE)
grid.goto(-GRID_CELL_SIZE * (NUMBER_SQUARES / 2 - 1), GRID_CELL_SIZE * NUMBER_SQUARES / 2)
grid.setheading(270)
for _ in range(NUMBER_SQUARES - 1):
grid.pendown()
grid.forward(NUMBER_SQUARES * GRID_CELL_SIZE)
grid.penup()
grid.goto(grid.xcor() + GRID_CELL_SIZE, GRID_CELL_SIZE * NUMBER_SQUARES / 2)
def follow_path(path_selection):
turtle = Turtle(visible=False)
x, y = ABSOLUTE_OFFSETS['Centre'] # relative to grid, not screen!
for direction, offset, marker in path_selection:
if direction in COMPASS_OFFSETS:
dx, dy = COMPASS_OFFSETS[direction]
if offset in ABSOLUTE_OFFSETS:
x, y = ABSOLUTE_OFFSETS[offset]
else:
x += dx * offset
y += dy * offset
turtle.penup()
# new virtual drawing origin, convert to screen coordinates
turtle.goto((x - NUMBER_SQUARES // 2) * GRID_CELL_SIZE, (y - NUMBER_SQUARES // 2) * GRID_CELL_SIZE)
MARKERS[marker](turtle)
turtle.penup()
def YouTube(turtle):
diameter = YOUTUBE_RADIUS * 2
x, y = turtle.position()
# Draws YouTube logo marker
turtle.goto(x + YOUTUBE_WIDTH/2 + YOUTUBE_RADIUS, y + YOUTUBE_HEIGHT/2 - YOUTUBE_RADIUS)
turtle.setheading(90)
# Draw the rounded rectangle (should really be a superellipse)
turtle.color(YOUTUBE_RED)
turtle.begin_fill()
for _ in range(2):
turtle.circle(YOUTUBE_RADIUS, 90)
turtle.forward(YOUTUBE_WIDTH)
turtle.circle(YOUTUBE_RADIUS, 90)
turtle.forward(YOUTUBE_HEIGHT - diameter)
# Finish up
turtle.end_fill()
# Return turtle position towards the centre of the rounded rectangle
turtle.goto(x - YOUTUBE_TRIANGLE_EDGE/4, y + YOUTUBE_TRIANGLE_EDGE/2)
turtle.setheading(90)
# Drawing the white 'play icon' triangle
turtle.fillcolor(YOUTUBE_WHITE)
turtle.begin_fill()
for _ in range(2):
turtle.right(120)
turtle.forward(YOUTUBE_TRIANGLE_EDGE)
# Finish up
turtle.end_fill()
def RedDot(turtle):
turtle.dot(GRID_CELL_SIZE / 2, 'Red')
def BlueDot(turtle):
turtle.dot(GRID_CELL_SIZE / 2, 'Blue')
def GreenDot(turtle):
turtle.dot(GRID_CELL_SIZE / 2, 'Green')
def OrangeDot(turtle):
turtle.dot(GRID_CELL_SIZE / 2, 'Orange')
MARKERS = [RedDot, BlueDot, GreenDot, YouTube, OrangeDot]
screen = Screen()
draw_grid() # for debugging
follow_path(path)
screen.mainloop()
I'm attempting to create a Rubik's Cube in Python, i have gotten as far as visually representing the cube. Struggling a bit with how to implement rotation.
I guess i'm asking for feedback as to how to go about doing this. I thought at first of, rotating each cubes set of vertices's, without much luck.
I basically want to select a slice from an array of cube objects (of varying size), perform a rotation and a translation on each object.
import pygame
import random
from pygame.locals import *
from OpenGL.GL import *
from OpenGL.GLU import *
vertices = (
(1, -1, -1),
(1, 1, -1),
(-1, 1, -1),
(-1, -1, -1),
(1, -1, 1),
(1, 1, 1),
(-1, -1, 1),
(-1, 1, 1)
)
edges = (
(0,1),
(0,3),
(0,4),
(2,1),
(2,3),
(2,7),
(6,3),
(6,4),
(6,7),
(5,1),
(5,4),
(5,7)
)
surfaces = (
(0,1,2,3),
(3,2,7,6),
(6,7,5,4),
(4,5,1,0),
(1,5,7,2),
(4,0,3,6)
)
colors = (
(1,0,0), #Red
(0,1,0), #Green
(1,0.5,0), #Orange
(1,1,0), #Yellow
(1,1,1), #White
(0,0,1), #Blue
)
class Cube():
'''set the vertices edges and surfaces(colored) for a Cube'''
def __init__(self):
'''initiate the display to show the cube'''
pygame.init()
display = (800,600)
pygame.display.set_mode(display, DOUBLEBUF|OPENGL)
glEnable(GL_DEPTH_TEST)
gluPerspective(45, (display[0]/display[1]), 0.1, 50.0)
glTranslatef(1,1, -40)
def setVertices(self, xmove, ymove, zmove):
'''set predefined vertices'''
xValueChange = xmove
yValueChange = ymove
zValueChange = zmove
newVertices = []
for vert in vertices:
newVert = []
newX = vert[0] + xValueChange
newY = vert[1] + yValueChange
newZ = vert[2] + zValueChange
newVert.append(newX)
newVert.append(newY)
newVert.append(newZ)
newVertices.append(newVert)
return newVertices
def CreateCube(self, vertices):
'''create with OpenGL'''
glBegin(GL_QUADS)
x = 0
for surface in surfaces:
glColor3fv(colors[x])
x+=1
for vertex in surface:
glVertex3fv(vertices[vertex])
glEnd()
class EntireCube():
def __init__(self,typeOfCube):
self.typeOfCube = typeOfCube
self.NewCube = Cube()
def createEntireCube(self):
'''for each dimension x,y,z make a dictionary containing the vertices to be displayed'''
self.cubeDict = {}
count = 0
for x in range(self.typeOfCube):
for y in range(self.typeOfCube):
for z in range(self.typeOfCube):
self.cubeDict[count] = self.NewCube.setVertices(x*2.1,y*2.1,z*2.1)
count += 1
def mainloop(self):
'''key events, creates the matrix of cubes'''
rotateUpKey, rotateDownKey, rotateLeftKey, rotateRightKey = False, False, False, False
rotationalSensitivity = 2
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
if event.type == KEYDOWN:
if event.key == K_UP:
rotateUpKey = True
if event.key == K_DOWN:
rotateDownKey = True
if event.key == K_LEFT:
rotateLeftKey = True
if event.key == K_RIGHT:
rotateRightKey = True
if event.type == KEYUP:
if event.key == K_UP:
rotateUpKey = False
if event.key == K_DOWN:
rotateDownKey = False
if event.key == K_LEFT:
rotateLeftKey = False
if event.key == K_RIGHT:
rotateRightKey = False
if rotateUpKey:
glRotatef(rotationalSensitivity,-rotationalSensitivity,0,0)
if rotateDownKey:
glRotatef(rotationalSensitivity,rotationalSensitivity,0,0)
if rotateLeftKey:
glRotatef(rotationalSensitivity,0,-rotationalSensitivity,0)
if rotateRightKey:
glRotatef(rotationalSensitivity,0,rotationalSensitivity,0)
#eventually implement keysbindings to call function to rotate a slice of the matrix created
# x = glGetDoublev(GL_MODELVIEW_MATRIX)
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)
for eachCube in self.cubeDict:
self.NewCube.CreateCube(self.cubeDict[eachCube])
# glPushMatrix()
# glRotatef(1,3,1,1)
# glPopMatrix()
pygame.display.flip()
pygame.time.wait(10)
def main():
NewEntireCube = EntireCube(3) #create a 3x3x3 cube
NewEntireCube.createEntireCube()
NewEntireCube.mainloop()
if __name__ == '__main__':
main()
pygame.quit()
quit()
I'm hoping someone who knows much more about this can give me some guidance as to how to proceed.
A rubik's cube can be organized by an 3 dimensional array of 3x3x3 cubes. It seems to be easy to rotate a slice of the cube, but note if on slice is rotated the positions of the cube change and have to be reorganized. Not only the position changes, also the orientation of the (rotated) single cubes changes.
First of all remove the PyGame and OpenGL initialization form the constructor of the class Cube. That is the wrong place for this. In the following will generate 27 objects of type Cube.
Each cube has to know where it is initially located (self.init_i) and where it is current located after some rotations (self.current_i). This information is encoded in a list with 3 elements, one for each axis. The values are indices of cube in the NxNxN rubik's cube in range [0, N[.
The orientation of a single cube is encoded in 3 dimensional Rotation matrix (self.rot). The rotation matrix has to be initialized by the identity matrix.
class Cube():
def __init__(self, id, N, scale):
self.N = N
self.scale = scale
self.init_i = [*id]
self.current_i = [*id]
self.rot = [[1 if i==j else 0 for i in range(3)] for j in range(3)]
Create a list of the 27 cubes
cr = range(3)
self.cubes = [Cube((x, y, z), 3, scale) for x in cr for y in cr for z in cr]
If a slice of the rubik's cube is rotated, then it has to be checked which of the single cubes is affected. This can be done by checking if the slice matches the entry of the rotation axis of the current position.
def isAffected(self, axis, slice, dir):
return self.current_i[axis] == slice
To rotate a cube, the position and the orientation has to be rotated by 90° around an axis. A 3 dimension rotation matrix consists of 3 direction vectors. A d dimensional vector can be rotated by swapping the coordinates of the vector and inverting the x coordinate of the result for a right rotation and inverting the y coordinate of the result for a left rotation:
rotate right: (x, y) -> (-y, x)
rotate left: (x, y) -> (y, -x)
Since all the vectors of the rotation matrix are in an axis aligned plane this algorithm can be used to change the orientation and the position of the cube. axis the rotation axis (x=0, y=1, z=2) and dir is the rotation direction (1 is right and -1 left)
To rotate the axis vector, 2 components of the vector have to be swapped and one of them inverted.
e.g rotate left around the Y-axis:
(x, y, z) -> (z, y, -x)
When the position is rotated, then the indices have to be swapped. Inverting an index means to map the index i to the index N-1-i:
e.g rotate left around the Y-axis:
(ix, iy, iz) -> (iz, iy, N-1-ix)
Rotation of a single cube:
i, j = (axis+1) % 3, (axis+2) % 3
for k in range(3):
self.rot[k][i], self.rot[k][j] = -self.rot[k][j]*dir, self.rot[k][i]*dir
self.current_i[i], self.current_i[j] = (
self.current_i[j] if dir < 0 else self.N - 1 - self.current_i[j],
self.current_i[i] if dir > 0 else self.N - 1 - self.current_i[i] )
When the cube has to be drawn, then the current position of the cube (self.current_i) and the orientation self.rot can be used to set up 4x4 transformation matrix:
def transformMat(self):
scaleA = [[s*self.scale for s in a] for a in self.rot]
scaleT = [(p-(self.N-1)/2)*2.1*self.scale for p in self.current_i]
return [
*scaleA[0], 0,
*scaleA[1], 0,
*scaleA[2], 0,
*scaleT, 1]
With glPushMatrix respectively glPushMatrix. By glMultMatrix a matrix can be multiplied to the current matrix.
The following function draws a single cube. The parameters angle, axis, slice, dir and it can even apply an animation to the cube, by setting animate=True and setting parameters angle, axis, slice, dir:
def draw(self, col, surf, vert, animate, angle, axis, slice, dir):
glPushMatrix()
if animate and self.isAffected(axis, slice, dir):
glRotatef( angle*dir, *[1 if i==axis else 0 for i in range(3)] )
glMultMatrixf( self.transformMat() )
glBegin(GL_QUADS)
for i in range(len(surf)):
glColor3fv(colors[i])
for j in surf[i]:
glVertex3fv(vertices[j])
glEnd()
glPopMatrix()
To draw the cubes, it is sufficient to call the method draw in a loop:
for cube in self.cubes:
cube.draw(colors, surfaces, vertices, animate, animate_ang, *action)
The implementation of the class Cube works for any NxNxN Rubik's cube.
See the example program for a 3x3x3 cube. The slices of the cube are rotated to the right by the keys 1 to 9 and to the left by the keys F1 to F9:
Of course the code uses the Legacy OpenGL in regard to your original code. But the method Cube.transformMat sets a general 4x4 model matrix for a single partial cube. Thus it is possible to port this code to modern OpenGL with ease.
import pygame
import random
from pygame.locals import *
from OpenGL.GL import *
from OpenGL.GLU import *
vertices = (
( 1, -1, -1), ( 1, 1, -1), (-1, 1, -1), (-1, -1, -1),
( 1, -1, 1), ( 1, 1, 1), (-1, -1, 1), (-1, 1, 1)
)
edges = ((0,1),(0,3),(0,4),(2,1),(2,3),(2,7),(6,3),(6,4),(6,7),(5,1),(5,4),(5,7))
surfaces = ((0, 1, 2, 3), (3, 2, 7, 6), (6, 7, 5, 4), (4, 5, 1, 0), (1, 5, 7, 2), (4, 0, 3, 6))
colors = ((1, 0, 0), (0, 1, 0), (1, 0.5, 0), (1, 1, 0), (1, 1, 1), (0, 0, 1))
class Cube():
def __init__(self, id, N, scale):
self.N = N
self.scale = scale
self.init_i = [*id]
self.current_i = [*id]
self.rot = [[1 if i==j else 0 for i in range(3)] for j in range(3)]
def isAffected(self, axis, slice, dir):
return self.current_i[axis] == slice
def update(self, axis, slice, dir):
if not self.isAffected(axis, slice, dir):
return
i, j = (axis+1) % 3, (axis+2) % 3
for k in range(3):
self.rot[k][i], self.rot[k][j] = -self.rot[k][j]*dir, self.rot[k][i]*dir
self.current_i[i], self.current_i[j] = (
self.current_i[j] if dir < 0 else self.N - 1 - self.current_i[j],
self.current_i[i] if dir > 0 else self.N - 1 - self.current_i[i] )
def transformMat(self):
scaleA = [[s*self.scale for s in a] for a in self.rot]
scaleT = [(p-(self.N-1)/2)*2.1*self.scale for p in self.current_i]
return [*scaleA[0], 0, *scaleA[1], 0, *scaleA[2], 0, *scaleT, 1]
def draw(self, col, surf, vert, animate, angle, axis, slice, dir):
glPushMatrix()
if animate and self.isAffected(axis, slice, dir):
glRotatef( angle*dir, *[1 if i==axis else 0 for i in range(3)] )
glMultMatrixf( self.transformMat() )
glBegin(GL_QUADS)
for i in range(len(surf)):
glColor3fv(colors[i])
for j in surf[i]:
glVertex3fv(vertices[j])
glEnd()
glPopMatrix()
class EntireCube():
def __init__(self, N, scale):
self.N = N
cr = range(self.N)
self.cubes = [Cube((x, y, z), self.N, scale) for x in cr for y in cr for z in cr]
def mainloop(self):
rot_cube_map = { K_UP: (-1, 0), K_DOWN: (1, 0), K_LEFT: (0, -1), K_RIGHT: (0, 1)}
rot_slice_map = {
K_1: (0, 0, 1), K_2: (0, 1, 1), K_3: (0, 2, 1), K_4: (1, 0, 1), K_5: (1, 1, 1),
K_6: (1, 2, 1), K_7: (2, 0, 1), K_8: (2, 1, 1), K_9: (2, 2, 1),
K_F1: (0, 0, -1), K_F2: (0, 1, -1), K_F3: (0, 2, -1), K_F4: (1, 0, -1), K_F5: (1, 1, -1),
K_F6: (1, 2, -1), K_F7: (2, 0, -1), K_F8: (2, 1, -1), K_F9: (2, 2, -1),
}
ang_x, ang_y, rot_cube = 0, 0, (0, 0)
animate, animate_ang, animate_speed = False, 0, 5
action = (0, 0, 0)
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
if event.type == KEYDOWN:
if event.key in rot_cube_map:
rot_cube = rot_cube_map[event.key]
if not animate and event.key in rot_slice_map:
animate, action = True, rot_slice_map[event.key]
if event.type == KEYUP:
if event.key in rot_cube_map:
rot_cube = (0, 0)
ang_x += rot_cube[0]*2
ang_y += rot_cube[1]*2
glMatrixMode(GL_MODELVIEW)
glLoadIdentity()
glTranslatef(0, 0, -40)
glRotatef(ang_y, 0, 1, 0)
glRotatef(ang_x, 1, 0, 0)
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)
if animate:
if animate_ang >= 90:
for cube in self.cubes:
cube.update(*action)
animate, animate_ang = False, 0
for cube in self.cubes:
cube.draw(colors, surfaces, vertices, animate, animate_ang, *action)
if animate:
animate_ang += animate_speed
pygame.display.flip()
pygame.time.wait(10)
def main():
pygame.init()
display = (800,600)
pygame.display.set_mode(display, DOUBLEBUF|OPENGL)
glEnable(GL_DEPTH_TEST)
glMatrixMode(GL_PROJECTION)
gluPerspective(45, (display[0]/display[1]), 0.1, 50.0)
NewEntireCube = EntireCube(3, 1.5)
NewEntireCube.mainloop()
if __name__ == '__main__':
main()
pygame.quit()
quit()
I'm new to Python and have a question. I want to move the turtle to a specific start location, and from there draw a shape. The shape has pre-determined coordinates, so I need to connect the points to make the shape.
I have to make 2 functions such that the following code calls those 2 functions and draws three shapes:
def testPolyLines():
# First square
squareShape = [(50, 0), (50, 50), (0, 50), (0, 0)]
drawPolyLine((200, 200), squareShape)
# Second square
drawPolyLine((-200, 200), squareShape, lineColour="green")
biggerSquareShape = generateSquarePoints(100)
# A triangle
triangleShape = [(200, 0), (100, 100), (0, 0)]
drawPolyLine((100, -100), triangleShape, fillColour="green")
def main():
testPolyLines()
main()
I made the first function to generate points for a square of any size:
def generateSquarePoints(i):
squareShape = [(i, 0), (i, i), (0, i), (0, 0)]
But I get stuck when it comes to actually drawing the shape. I can make the turtle go to the start position, but I don't know how to make it go through a list of points and connect them to form a shape. This is what I have:
def drawPolyLine(start, squareShape, lineColour="black", fillColour = "white"):
pencolor(lineColour)
fillcolor(fillColour)
penup()
goto(start)
pendown()
begin_fill()
goto(squareShape)
end_fill()
This is obviously not right...the part I'm confused about is how to tell the turtle to go to the list of points, and connect them along the way to form the shape. My program now only goes to the start positions but doesn't draw the shape.
I would really appreciate any help or advice! Thanks in advance.
Issues with your code: you can't just goto() the points, you need to adjust them to the starting position, treating the x & y in the point as more of a delta-x, delta-y; generateSquarePoints() needs to return its list of points, not assign it; obviously a for loop is needed as others have mentioned; you need to explicitly draw back to the starting point to close the shape.
Try the following rework of your code to see if it does what you want:
import turtle
def generateSquarePoints(i):
""" generate points for a square of any size """
return [(i, 0), (i, i), (0, i), (0, 0)]
def drawPolyLine(start, points, lineColour="black", fillColour="white"):
""" draw shapes using a list of coordinates """
turtle.pencolor(lineColour)
turtle.fillcolor(fillColour)
turtle.penup()
turtle.goto(start) # make the turtle go to the start position
turtle.pendown()
turtle.begin_fill()
x, y = start
for point in points: # go through a list of (relative) points
dx, dy = point
turtle.goto(x + dx, y + dy)
turtle.goto(start) # connect them to start to form a closed shape
turtle.end_fill()
turtle.penup()
if __name__ == "__main__":
def testPolyLines():
""" test shapes shape drawing functions """
# First square
squareShape = [(50, 0), (50, 50), (0, 50), (0, 0)]
drawPolyLine((200, 200), squareShape)
# Second square
biggerSquareShape = generateSquarePoints(100)
drawPolyLine((-200, 200), biggerSquareShape, lineColour="green")
# A triangle
triangleShape = [(200, 0), (100, 100), (0, 0)]
drawPolyLine((100, -100), triangleShape, fillColour="green")
def main():
testPolyLines()
turtle.done()
main()