Get color of coordinate of figure drawn with Python Zelle graphics - python

In python, How can I get the color of a specific coordinate of any figure, that I've drawn with the Zelle graphics module?
I'm using Python with the Zelle graphics module to process with my circles and lines. I'm trying to get a color of aspecific coordinate (or pixel?) on the canvas I'm drawing on. What method or other modules do I have to use in order to achieve this?
I thought the getPixel() method would work, but it does not since it's for image processing, not for drawn pictures. My current code:
from math import *
from time import *
from graphics import *
def main():
paper = GraphWin('shjaji20', 300, 300)
paper.setBackground('white')
road0 = Circle(Point(150, 150), 100)
road1 = Line(Point(150, 50), Point(150, 0))
road2 = Line(Point(50, 150), Point(0, 150))
road3 = Line(Point(250, 150), Point(300, 150))
road4 = Line(Point(150, 250), Point(150, 300))
road0.draw(paper)
road1.draw(paper)
road2.draw(paper)
road3.draw(paper)
road4.draw(paper)
car = Circle(Point(0, 150), 5)
car.setFill('white')
car.draw(paper)
for i in range(1000):
car.move(1, 0)
time.sleep(.05)
print car.getPixel(150, 0) ***#I tried many ways but don't work! Here's the problem***
main()

This can be done, in a way. Zelle's graphics.py is built atop Python's tkinter library which can both identify which graphic object sits above a given point as well as interrogate that object's color. The key is knowing that a GraphWin instance is also a tkinter Canvas by inheritance:
from time import sleep
from graphics import *
paper = GraphWin(width=300, height=300)
road = Circle(Point(150, 150), 100)
road.setFill('pink')
road.draw(paper)
Line(Point(150, 50), Point(150, 0)).draw(paper)
Line(Point(50, 150), Point(0, 150)).draw(paper)
Line(Point(250, 150), Point(300, 150)).draw(paper)
Line(Point(150, 250), Point(150, 300)).draw(paper)
car = Circle(Point(0, 150), 5)
car.setFill('white')
car.draw(paper)
for _ in range(300):
car.move(1, 0)
center = car.getCenter()
overlapping = paper.find_overlapping(center.x, center.y, center.x, center.y)
if overlapping:
print(paper.itemcget(overlapping[0], "fill"))
sleep(0.05)
As the small circle moves across the lines, "black" will be printed to the console. As it moves across the central circle, "pink" we be printed. The code is for Python3, if you're using Python2 you'll need to adjust.

Related

Moving a part of the screen with pygame in python 3

I'm making a game, a part of which includes a chat-box style simulation. What I'm trying to do is to move a part of the screen upwards so all the text will move up and make room for more.
I've succeeded in making part of the screen black using this code:
def move (screen):
area = pygame.Surface((540, 400))
area.scroll(0, -100)
area_rect = area.get_rect()
area_rect = area.get_rect(left=100, bottom=400)
area_rect.move_ip(0, -100)
screen.blit(area, (100, 0), area_rect)
pygame.display.flip()
I'm trying to move the area [(100, 0), (640, 400)] up by 100 pixels on a 640x480 screen. What am I doing terribly wrong?
You dont need to use Surface.scroll for that. If you don't care what's left below after moving that specific area upwards, try just copying the part that you want to move and blitting it where you want it to reappear:
area_rect = pygame.Rect(100, 0, 540, 400)
area = screen.subsurface(area_rect)
new_area_rect = area_rect.move(0, -100)
screen.blit(area, new_area_rect.topleft)
pygame.display.flip()

Additive blending in pygame doesn't work with alpha

I recently discovered the different blending modes you can apply to blitted surfaces in pygame and I wanted to see how flexible the system was. Unless I'm doing something wrong, it's apparently pretty limited (just like the rest of pygame OOOOOOOH shots fired). I wrote a simple program that draws a bunch of gradient circles using alpha and blits them all around the screen. This is the code:
import pygame
import pygame.gfxdraw
pygame.init()
import random
SCREEN = pygame.display.set_mode((800, 600))
SCREEN.fill((0, 0, 0))
def draw_square(surface, colour, x, y):
"""
Yeah it's called draw square but it actually draws a circle thing I was just too lazy
to change the name so you gotta deal with it.
"""
square = pygame.Surface((100, 100))
square.fill((0, 0, 0))
colour += (int(15/255*100), )
for i in range(25):
pygame.gfxdraw.filled_circle(square, 50, 50, i*2, colour)
# Comment the previous two lines out and uncomment the next line to see different results.
# pygame.draw.circle(square, colour[:3], (50, 50), 50)
surface.blit(square, (x - 50, y - 50), special_flags=pygame.BLEND_RGB_ADD)
running = True
while running:
for evt in pygame.event.get():
if evt.type == pygame.QUIT:
running = False
draw_square(SCREEN, (25, 255, 25), random.randint(0, 800), random.randint(0, 600))
pygame.display.update()
pygame.quit()
It seems to work when drawing a normal circle, but when drawing the circles with pygame.gfxdraw.filled_circle additive blending doesn't work. Any ideas?
EDIT: I'm using Python 3, so 15/255 evaluates properly to a float.
The issue is still with this line:
colour += (int(15/255*100), )
It should go to white initially, but the alpha is so low it will take a long time (well, it should in theory...).
Doing:
colour += (int(125/255*100), )
Makes the effect more obvious.
Result:

pygame - trying to move a rectangle

I am codding a drum game (based on dtx-Mania).
I got an issue on how to draw a rectangle and move it. I can make a static one, but not a moving one. I currently used a line but it seams pygame draw it as a rectangle so far if it as an impact i will change back to rectangle.
My goal is to draw the rectangle and move it at a slow enough pace so that it takes about 1 second to get to a line.
I know I still have a lot to learn, this is what I got to test so far.
#!/usr/bin/env python3
#-*- coding:utf-8 -*-
#small exemple of a moving rectangle
import pygame, sys
pygame.init()
fpsClock = pygame.time.Clock()
windowsSurfaceObj = pygame.display.set_mode((640, 480))
pygame.display.set_caption('moving rectangle test')
white = pygame.Color(255, 255, 255)
black = pygame.Color(0, 0, 0)
step = pygame.draw.line(windowsSurfaceObj, white, (233, 0), (269, 0), 6)
step
while True:
windowsSurfaceObj.fill(black)
#the coordonate are moved but the rectangle is now drew
step.move(0, -1)
#this is the target line (where the moving object must go to)
pygame.draw.line(windowsSurfaceObj, white, (90, 420), (390, 420), 6)
pygame.display.update()
fpsClock.tick(30)
Thank you for your help.
It is always good to read the docs. From the pygame docs:
line(Surface, color, start_pos, end_pos, width=1) -> Rect
Draw a straight line segment on a Surface. There are no endcaps, the
ends are squared off for thick lines.
In the description text of the whole module:
The functions return a rectangle representing the bounding area of changed pixels.
So you draw your first line, and move a rectangle representing a bounding are of changed pixels. Since you do not redraw your line, your first line disappears.
To solve this, you need to draw the line in the while loop after moving.
step.move(0, -1)
pygame.draw.rect(windowsSurfaceObj, white,step, 6)

drawing a point on the screen every 17ms in Python?

I managed to string together a script that receives commands from an iOS app setting velocity and a direction.
The thing is I do not have the actual device, so my app instead sends commands to a little python web socket server I built that uses tornado...
Essentially what I would ideally need is a way to:
Display a window
Every 17ms, clear the window, read a global variable with x and y and draw a point or circle at x and y.
Is there a convenient way to do this so I can visually see what's going on?
If I can get something to draw a circle in a window every X ms, I can handle the rest.
What needs to be added:
-create a window
-create a timer
on timer callback: clear screen and draw a circle in the window.
You should try using pygame for graphics work.
First download pygame
Here is a sample code
import pygame,sys
from pygame import *
WIDTH = 480
HEIGHT = 480
WHITE = (255,255,255) #RGB
BLACK = (0,0,0) #RGB
pygame.init()
screen = display.set_mode((WIDTH,HEIGHT),0,32)
display.set_caption("Name of Application")
screen.fill(WHITE)
timer = pygame.time.Clock()
pos_on_screen, radius = (50, 50), 20
while True:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
timer.tick(60) #60 times per second you can do the math for 17 ms
draw.circle(screen, BLACK, pos_on_screen, radius)
display.update()
HOPE THAT HELPS. Remember you need to download pygame first.
You should also read up on pygame. It is really helpful.
You could use your terminal as a "window" and draw a "circle" in it. As a very simple (and unreliable) "timer", time.sleep() function could be used:
#!/usr/bin/env python
"""Print red circle walking randomly in the terminal."""
import random
import time
from blessings import Terminal # $ pip install blessings colorama
import colorama; colorama.init() # for Windows support (not tested)
directions = [(-1, -1), (-1, 0), (-1, 1),
( 0, -1), ( 0, 1),
( 1, -1), ( 1, 0), ( 1, 1)]
t = Terminal()
with t.fullscreen(), t.hidden_cursor():
cur_y, cur_x = t.height // 2, t.width // 2 # center of the screen
nsteps = min(cur_y, cur_x)**2 # average distance for random walker: sqrt(N)
for _ in range(nsteps):
y, x = random.choice(directions)
cur_y += y; cur_x += x # update current coordinates
print(t.move(cur_y, cur_x) +
t.bold_red(u'\N{BLACK CIRCLE}')) # draw circle
time.sleep(6 * 0.017) # it may sleep both less and more time
print(t.clear) # clear screen
To try it, save the code into random-walker.py and run it:
$ python random-walker.py
I don't know whether it works on Windows.
1. Create a window
2. Set a timer instance and repetition tasks
3. Draw a circle

How to draw to an off-screen display in PyGame

I'm doing a graphics test using PyGame to simulate the Dragon Curve being unfolded. I already made one successful version that keeps track of all the points as they rotate around each other, but obviously, this begins to slow down pretty substantially after a few iterations. In order to speed this up, I want to simply store the drawn segments into an image variable, and continually save a segment of the screen to a variable and draw those moving rather than keeping track of a lot of points. How can I do either of the following?
Draw to an off-screen image variable that then gets drawn to the screen in the correct place
Save a section of the visible display into an image variable
I tried reading through some of the PyGame documentation, but I didn't have any success.
Thanks!
Creating an additional surface object, and drawing to it is the solution. This surface object can then be drawn onto the display's surface object as shown below.
More information on the PyGame Surface object can be found here
import pygame, sys
SCREEN_SIZE = (600, 400)
BG_COLOR = (0, 0, 0)
LINE_COLOR = (0, 255, 0)
pygame.init()
clock = pygame.time.Clock() # to keep the framerate down
image1 = pygame.Surface((50, 50))
image2 = pygame.Surface((50, 50))
image1.set_colorkey((0, 0, 0)) # The default background color is black
image2.set_colorkey((0, 0, 0)) # and I want drawings with transparency
screen = pygame.display.set_mode(SCREEN_SIZE, 0, 32)
screen.fill(BG_COLOR)
# Draw to two different images off-screen
pygame.draw.line(image1, LINE_COLOR, (0, 0), (49, 49))
pygame.draw.line(image2, LINE_COLOR, (49, 0), (0, 49))
# Optimize the images after they're drawn
image1.convert()
image2.convert()
# Get the area in the middle of the visible screen where our images would fit
draw_area = image1.get_rect().move(SCREEN_SIZE[0] / 2 - 25,
SCREEN_SIZE[1] / 2 - 25)
# Draw our two off-screen images to the visible screen
screen.blit(image1, draw_area)
screen.blit(image2, draw_area)
# Display changes to the visible screen
pygame.display.flip()
# Keep the window from closing as soon as it's finished drawing
# Close the window gracefully upon hitting the close button
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit(0)
clock.tick(30)

Categories