The section of code is:
originalpipey = random.randint(0, 500)
pipey = 0 - originalpipey
twopipey = pipey + 650
def spawnpipe(originalpipey, pipey, twopipey):
screen.blit(pipe,(pipex, 0 - originalpipey))
screen.blit(pipe2,(pipex, twopipey))
The original pipe y is how far down the page I want the pipe to be. The final pipe y is then 0 minus that, so that it goes above the screen and then goes that far down (I worked it out). The two pipe y is the second pipe y, basically just the original one add 650, which creates a 100 pixel gap between the two because I made the pipe png in photoshop 550 pixels tall.
I am making a Flappy Bird type game and this code is to make the Y size of the pipe. Whenever I use the function like this, it is the same size. However, if I put the random integer into the function, to make a new size, it just constantly changes the size. Is there any way to pick a new size each time is is repeated? Thanks.
To have a new random integer every time a function is called call randint inside the function.
def myfunc():
r = random.randint(0, 500) # R is set every time function is called
Related
I have this code:
def block_stacks(num):
stack = cmds.group(empty=True, name='Stacks#')
size = num
for var in range(num):
i = 0
r_rot = random.uniform(0,359)
block = cmds.polyCube(h=0.5, w=0.5, d=0.5, name='block#')
cmds.parent(block, stack)
cmds.move(0, 5.38 + i, 0, 'block*')
cmds.rotate(0, r_rot, 0, 'block*')
rR= random.uniform(0, 1.0)
rG= random.uniform(0, 1.0)
rB= random.uniform(0, 1.0)
cmds.polyColorPerVertex('block*', rgb=[rR,rG,rB], cdo = True)
i+=0.5
block_stacks(5)
in Maya's Script Editor. When I run it, the random rotation, and random color work fine, and the block places at the correct location, but it only creates 1 block instead of 5 (like I intend for it to) and says
"Warning: Cannot parent components or objects in the underworld."
multiple times. I have absolutely no idea what this means, and apparently there is no answer anywhere on the entire internet that says what exactly this error is. It still creates the object when I run it, and it doesn't give any red error message. Does anyone know what this means, and why it only makes a stack 1 block high instead of 5 like it's supposed to? I've been trying to fix this for almost 2 hours and I'm pretty much burnt out now.
I believe the error means that you can't parent a dg node (something that has no transform) to a dag node. For example, try parenting an objectSet to a transform. It won't let you, because dg nodes have no transforms themselves and cannot belong in a hierarchy.
Now it's giving you this error because you're trying to parent the cube's polyCube input, which has no transform! This is being done by accident because you're assuming that cmds.polyCube returns the cube's transform. It does not. In fact, it returns a list of 2 items: the cube's transform, and the cube's polyCube input. And since cmds.parent can accept a list in its first parameter, you are essentially trying to parent the transform AND polyCube to the stack transform. You can easily avoid this by grabbing the command's first index like this: cmds.polyCube()[0]
Now another issue is that all of the cubes move to the same place. This is because your i variable is INSIDE the for loop. So every iteration i resets to 0 instead of being incremented, thus they all move to the same position.
Another issue is that in a lot of your commands you are using "block*". Doing this doesn't refer to the block variable, instead it will actually grab all transforms that start with the name "block". In fact you don't need the "*" at all, just pass the variable block.
With all of this in mind, here's the working code:
import random
import maya.cmds as cmds
def block_stacks(num):
stack = cmds.group(empty=True, name='Stacks#')
i = 0 # Need to move this OUT of the loop otherwise it always resets to 0 and all of the blocks will move to the same place.
for var in range(num):
r_rot = random.uniform(0,359)
block = cmds.polyCube(h=0.5, w=0.5, d=0.5, name='block#')[0] # This command actually returns a list of 2 items, the transform and the polyCube input, so grab the first index.
cmds.parent(block, stack)
cmds.move(0, 5.38 + i, 0, block) # Pass the variable.
cmds.rotate(0, r_rot, 0, block)
rR = random.uniform(0, 1.0)
rG = random.uniform(0, 1.0)
rB = random.uniform(0, 1.0)
cmds.polyColorPerVertex(block, rgb=[rR, rG, rB], cdo=True)
i += 0.5
block_stacks(5)
In this code I can't see why it isn't printing a hexagon 24 times. I tell it to make a 6 sided shape with 60 degrees between lines ( a hexagon) and tell it do turn 15 degrees each time. This ends up being a even 24 for the picture I'm trying to draw.
import turtle
Hex_Count = 0
x = turtle.Turtle()
x.speed(.25)
def Hexagon():
for i in range(24):
for i in range(6):
x.forward(100)
x.left(60)
Hex_Count = Hex_Count + 1
x.left(15)
print(Hex_Count)
Hexagon
But, for some reason, when I run this code the turtle screen pops up for about a half second then closes. How do I get it to perform in the way I want it to?
You have several errors that I corrected for you; I added the explanation in the comments:
import turtle
hexagons_count = 0
my_turtle = turtle.Turtle() # x is not a good name for a Turtle object
# my_turtle.speed(.25) # see #cdlane comment reported in a note under.
def draw_hexagon(): # use explicit names respecting python conventions (no camel case)
global hexagons_count # need global to modify the variable in the function scope
for idx in range(24): # use different dummy variable names in your loops
for jdx in range(6): # use different dummy variable names in your loops
my_turtle.forward(100)
my_turtle.left(60)
hexagons_count += 1
my_turtle.left(15)
print(hexagons_count)
draw_hexagon() # need parenthesis to call the function
turtle.exitonclick() # this to exit cleanly
Note: I know you simply copied it from the OP but my_turtle.speed(.25)
doesn't make sense as the argument should be an int from 0 to 10 or a
string like 'slow', 'fastest', etc. I especially don't understand why
beginners with turtle code that isn't working call turtle.speed() at
all -- it seems to me a function to be tweaked after everything is
working. #cdlane
You have some reference issue, you just need to put the variable hex_count where it needs to be so you don't have error accessing it.
import turtle
x = turtle.Turtle()
x.speed(.25)
def Hexagon():
Hex_Count = 0
for i in range(24):
for i in range(6):
x.forward(100)
x.left(60)
Hex_Count += 1
x.left(15)
print(Hex_Count)
Hexagon()
prints 24
You have several problems with your program. One is that it will when after running through the program, closing the window it created. You can add turtle.exitonclick() to the end of your script which tells python to wait for a click in the graphics window, after which it will exit.
The second problem is that you don't call the Hexagon function because you're missing the parentheses. Even if a function takes no arguments, you still need to call it like:
Hexagon()
The final problem is that you need to define Hex_Count before you try to increment it. Hex_Count + 1 will thrown an error if Hex_Count wasn't already assigned to. You can fix this by putting
Hex_Count = 0
before your for loop in Hexagon.
An approach different in a lot of the details but primarily in its use of circle() to more rapidly draw the hexagons:
from turtle import Turtle, Screen # force object-oriented turtle
hex_count = 0 # global to count all hexagons drawn by all routines
def hexagons(turtle):
global hex_count # needed as this function *changes* hex_count
for _ in range(24): # don't need explicit iteration variable
turtle.circle(100, steps=6) # use circle() to draw hexagons
turtle.left(15) # 24 hexagons offset by 15 degrees = 360
hex_count += 1 # increment global hexagon count
print(hex_count)
screen = Screen()
yertle = Turtle(visible=False) # keep turtle out of the drawing
yertle.speed('fastest') # ask turtle to draw as fast as it can
hexagons(yertle)
screen.exitonclick() # allow dismiss of window by clicking on it
I can't figure out how can I finish one simple program written in Python. Program basically generates array of ten random numbers and then sorts them using bubblesort algorithm. Whole shorting process should be shown on screen - such as this one
My current code is this:
import tkinter
import random
canvas = tkinter.Canvas(bg='white',width='800',height='400')
canvas.pack()
c = []
for i in range(0,10):
c=c+[random.randrange(10)]
print(c)
print('Zoradenie...', c)
def sort(c):
x=300
for i in range(0,10):
for j in range(0,len(c)-1-1):
if c[j+1]<c[j]:
c[j+1],c[j]=c[j],c[j+1]
canvas.create_text(300,80,text=c[j],fill='Red')
x+=25
canvas.update()
canvas.after(1000)
print(c)
return c
sort(c)
But I can't figure out how to show numbers on screen. Any ideas?
To display the digits on the canvas, you must create a text item for each digit. See the end of my code. The harder part is moving the digits. One way is to delete and recreate; the other is to move. I choose the latter.
The hardest part, perhaps, is the time delays. If one uses mainloop, one should use after rather than time.sleep (which blocks the looping) and not use for-loops for animation. The problem is that the function (here sort) that naturally contains for-loops must be broken into pieces whose joint operation may be hard to understand. If one is running just one function and does not care about user interaction (for instance, a pause button), one can use time.sleep and update. I have done so here to make what is going on clearer.
from random import randrange
from time import sleep
import tkinter as tk
root = tk.Tk()
canvas = tk.Canvas(root, bg='white', width='800', height='400')
canvas.pack()
ndigits = 10
digits = [randrange(10) for _ in range(ndigits)]
tdelta1, tdelta2 = .8, .2
xstart = 300
xdelta = 25
y = 80
def color(i, swap):
"Temporarily color digits i and i+i according to swap needed."
x = xstart + xdelta * i
dcolor = 'Red' if swap else 'green'
canvas.itemconfigure(items[i], fill=dcolor)
canvas.itemconfigure(items[i+1],fill=dcolor)
canvas.update()
sleep(tdelta1)
canvas.itemconfigure(items[i], fill='Black')
canvas.itemconfigure(items[i+1], fill='Black')
canvas.update()
sleep(tdelta2)
def swap(i):
digits[i], digits[i+1] = digits[i+1], digits[i]
canvas.move(items[i], xdelta, 0)
canvas.move(items[i+1], -xdelta, 0)
items[i], items[i+1] = items[i+1], items[i]
def bubsort():
"Sort digits and animate."
for stop in reversed(range(1, ndigits)):
# stop = index of position whose entry will be determined.
for i in range(stop):
swap_needed = digits[i] > digits[i+1]
color(i, swap_needed)
if swap_needed:
swap(i)
color(i, False)
# Create display items and pause.
items = [canvas.create_text(xstart + xdelta*i, y, text=str(digit))
for i, digit in enumerate(digits)]
canvas.update()
sleep(tdelta1)
bubsort()
This code makes it fairly easy to replace the text digit display with, for instance, a colored bar display. To develop this further, I would define a class of items combining int values and display items as attributes. There would them be only one array of combined items. With comparison methods defines, the array could be passed to any sort function.
I am currently in the process of making a new cannon game. How can I make it so that there is just one cannon, on the bottom left hand of the screen?
from graphics import *
from math import sqrt
from math import trunc
def PinR(p,r):
if p.getX()>=r.getP1().getX() and p.getX()<=r.getP2().getX()and p.getY()>=r.getP1().getY() and p.getY()<=r.getP2().getY():
return True;
else:
return False;
def distance(p1,p2):
dx=p1.getX()-p2.getX();
dy=p1.getY()-p2.getY();
dist=sqrt(dx*dx+dy*dy);
return dist;
#parameter
FieldWidth=700;
FieldHeight=700;
GroundDepth=75;
BallSize=10;
OriginalSpeed=4;
FieldBackground="brown";
FieldBorder="brown";
tickLength=800000;
buttonSize=8;
# number of cannons and balls
numBalls=4;
# initial cannon power
explosionStrength=30;
# intial gravitational constant
g=1;
# clock tick delay
delay=0.05;
#Create field
Field=GraphWin("B",FieldWidth,FieldHeight);
Field.setBackground(FieldBackground);
#set of balls
spacing=FieldWidth/(numBalls);
ball=[];
for b in range (0,numBalls):
newball=Circle(Point(spacing*b+spacing//2,FieldHeight-GroundDepth),BallSize);
newball.setFill("black");
newball.draw(Field);
ball.append(newball);
#cannon
cannon=[]
for c in range (0,numBalls):
newCannon=Rectangle(Point(spacing*c+spacing//2-BallSize,FieldHeight-GroundDepth-BallSize*5),
Point(spacing*c+spacing//2+BallSize,FieldHeight-GroundDepth+BallSize));
newCannon.setFill("black");
newCannon.draw(Field);
cannon.append(newCannon);
#set of button groups (fire, powerup, powerdown)
fire=[];
for f in range (0,numBalls):
newbutton=Rectangle(Point(spacing*f+spacing//2-buttonSize//2,FieldHeight-GroundDepth-BallSize),
Point(spacing*f+spacing//2+buttonSize//2,FieldHeight-GroundDepth-BallSize+buttonSize));
newbutton.setFill("red");
newbutton.draw(Field);
fire.append(newbutton);
#wall
#target(red,white,red,white)
balldistance=20;
ball1=Circle(Point(FieldWidth//2-20,FieldHeight//2+20),BallSize);
ball1.setFill("red");
ball1.draw(Field);
The reason you get 4 cannons is that you're doing this:
for c in range (0,numBalls):
… where numBalls is 4, and you create a new cannon each time through the loop.
Presumably with only 1 cannon you also only want one cannon ball and one shot, so just set numBalls = 1 instead of numBalls = 4.
However, it might make more sense to simplify the program while you're at it. Replace the lists of 4 cannons with a single cannon, get rid of the loop, do the same for the 4 balls, etc. Then you can also simplify the layout rules—no need for a spacing variable to configure how far apart the cannons are if there's only 1 of them. And so on. This might make it easier for you to understand how the program works—and figuring out how to simplify it might similarly be beneficial on its own.
And if you want to change its position, that's being set in this line:
newCannon=Rectangle(Point(spacing*c+spacing//2-BallSize,FieldHeight-GroundDepth-BallSize*5),
Point(spacing*c+spacing//2+BallSize,FieldHeight-GroundDepth+BallSize));
So, you can tweak the various constants (which all seem to have pretty reasonable names) to get the result you want—or, of course, just hardcode the position you want instead of calculating it.
So, what I am trying to do in detail:
I have a device that acts as a display, although is technically not one (that's not really important, it can be handled like a normal display) and I want to display a series of images on it. When each image is displayed i call a function that takes readings from another device. So far I have used pyglet for that and I can get it to display the images in the correct order and where I want them, but the readings taken seem not to correspond to the right image.
The simplest way to explain what I want to do is:
for a in range(10):
display('image%d'%a)
values(a) = measure()
Imagine values being initiated in the correct form.
What I tried so far was:
import pyglet
import numpy as np
size = 64
no = 512/size
a,b,c = (0,0,0)
values = np.zeros((no,no,3))
display = pyglet.window.get_platform().get_default_display()
screens = []
for screen in display.get_screens():
screens.append(screen)
window = pyglet.window.Window(screen = screens[1], fullscreen=1)
#here i choose the mentioned device, since it is connected to my computer via display port
#window.event
def update(dt):
global a,b,c
if a == no/2. and b == no/2.:
values[a,b,c] = 0
window.clear()
else:
image = pyglet.image.load('folder_%d/grating_%d_%d_%d.bmp' % (size,a,b,c))
window.clear()
print (a,b,c)
image.blit(0,0)
values[a,b,c] = measure()
c+=1
if c == 3:
b += 1
c = 0
if b == no:
a += 1
b = 0
if a == no:
pyglet.app.exit()
pyglet.clock.schedule_interval(update, .2)
pyglet.app.run()
where measure() is my own function. "no" is an index for my images, they range from (0,0,0),(0,0,1),(0,0,2),(0,1,0)... to (no,no,2) and are called to be called one by one. Also the case of a = b = no/2 is a special case that is of no special importance to my problem, I think.
first of all: I am pretty sure this is neither elegant nor efficient but I am not creating software that anyone else is ever likely to use. I am also aware that using global variables is bad practice but their use is due to me not knowing how to use eventloops correctly.
I am not happy with this solution, because the readings i take always seem to correspond to the previous image.
I guess I misuse the eventloop badly, but the pyglet documentation does not really help me here.
Also I feel like I am building a whole truck just to carry a bag across the street...
I have already looked into pyplot as an alternative, since the imshow() function works in the way I want, but the plotting libraries seem to display images in random sizes, which I cannot figure out how to control properly.
I appreciate any help on using pyglet correctly as well as alternative libraries that can help.
Thank you already,
Mopsi
An extra-long comment, that requires formatted code
From your example, you don't need a,b,c outside of the update function and all the global stuff is about having values that stay alive across invocations. If I'm correct this is better suited by a closure, like
...
def make_update(no, window):
from itertools import product
abcs = product(range(no),range(no),range(3))
#window.event
def _update(...):
try:
a, b, c = next(abcs)
except StopIteration:
... wind up ...
...
return _update
update = make_update(no, window)
...
Alright, I did not actually solve the problem but found a workaround:
I just flatten my image nomenclature, e.g
0_0_0 -> 000
0_0_1 -> 001
0_0_2 -> 002
0_1_0 -> 003
etc.
With values now being an array with dimensions [no*no*3,1]
And since for the n-th iteration and therefore n-th measurement I see the (n-1)th image, I simply add a dummy image and assign the n-th measured value to values[n-1].
The first measurement being useless is no problem here, since values[-1] is the last element, which gets overwritten with a meaningful measurement in the end.
Since the number of images is known and predetermined I can reshape my array of values afterwards.
If anyone cares to explain why no the displayed image is shifted by one iteration (with no image at all being displayed at the first iteration) please go ahead.