python tkinter rectangle resize - python

how can i resize my rectangle(canvas_bar) ?
am making hp bar to follow the object(monster)
and need to resize by it hp
hp = 100
hp_x = 100/5
canvas.create_rectangle(self.x, self.y, self.x+20, self.y+hp_x,
fill='red')
self.canvas.move(self.canvas_bar, self.vx, self.vy)
enter image description here

You can use the coords method to change the coordinates of an object.
The following example gets the current coordinates for the item identified by self.canvas_bar, and then makes the bar 100px wider:
(x0, y0, x1, y1) = self.canvas.coords(self.canvas_bar)
self.canvas.coords(self.canvas_bar, (x0, y0, x1+100, y1))

Related

How do I make a sprite "stand' on another sprite in pygame?

I've got two sprites that can detect collisions, but I'm not sure how I can make my character sprite "stand" on my platform. Nothing I've done seems to work.
If you have 2 pygame.Rect objects, you can move the 2nd rectangle on the 1st rectangle by setting the bottom of the 2nd rectangle with the top of the 1st rectangle. With the virtual attributes of pygame.Rect it is easy to do so:
rect2.bottom = rect1.top
Or if you have 2 pygame.sprite.Sprite objects:
sprite2.rect.bottom = sprote1.rect.top
If you have 2 pygame.Surface objects (surf1 and surf2) and the 2 corresponding positions (x1, y1) and (x2, y2), use get_rect() to create pygame.Rect objects from the Surfaces. Move the 2nd rectangle on the 1st rectangle and update the position of the 2nd rectangle:
rect1 = surf1.get_rect(topleft = (x1, y1))
rect2 = surf2.get_rect(topleft = (x2, y2))
rect2.bottom = rect1.top
y2 = rect2.y

How to automatically rotate images if they are vertical

I recently starting coding a few days ago and I'm trying to write a program that crops images and then stacks them. I am currently still on step one. I want to make it where after the image is cropped, if is no already, rotate it to the horizontal position. Thank you for your time.
Edit: So I was able to get it to rotate, but now my rotated file has giant black boxes at the top and bottom, anyone know how to remove that.
from PIL import Image
# Convert list in variables
print("Type in the coordinates for the upper left (x1,y1) and bottom right (x2,y2) points")
coordinates = list(map(int, input("Separate values with a space (x1 y1 x2 y2): ").strip().split()))[:4]
x1, y1, x2, y2 = coordinates
print("Generating image...")
# Accessing file from folder
im = Image.open("C:\\Users\\Alex\\Desktop\\Ps\\2.tiff")
# Cropping function
selected_region = (x1, y1, x2, y2)
cropped_region = im.crop(selected_region)
# Current line I am trying to add to rotate images
selected_region = (x1, y1, x2, y2)
cropped_region = im.crop(selected_region)
if (y2-y1)>(x2-x1):
rotated_image = cropped_region.rotate(90)
else:
rotated_image = cropped_region
cropped_region.show()
cropped_region.save("C:\\Users\\Alex\Desktop\\Ps\\Output\\2_cropped.tiff", quality=95)
rotated_image.save("C:\\Users\\Alex\Desktop\\Ps\\Output\\rotated.tiff", quality=95)
Also, hopefully this isn't asking for too much. So in this code, I am cropping one image, is there a way I can repeat this for all (about 500) images in the same folder (all labelled test1.tiff, test2.tiff, test3.tiff...)

Pygame circle and its associated rect for collision detection

I am having an issue with Pygame drawing a circle and its associated rect. When I draw a circle such as pygame.draw.circle(surface, color, center, radius) it creates a rect. I am attempting to do collision detection using pygame.collidepoint(event.pos) where event.pos is the position of a mouse click. The size of my window is 500x400 and has a black background and the drawn circle is blue. When I click outside of the circle (in the black background), the circle should increase in size by multiplying the radius by an int. Conversely, when a click is registered inside of the circle, the circle shrinks by dividing the radius by an int.
The problem I am having is that the rect is not actually the same size as the circle such that when you click on the background when the circle is large but not completely filling the window, it shrinks instead of getting bigger (i.e. it registers a click inside the circle). At a certain point, the rect associated with the circle becomes the same size as the window even if the circle is not completely filling it which results in registering a click inside.
My question is how can I use hit detection for the circle only and not the rect which is larger than the actual circle?
Here is the relevant code:
def handleMouseDown(self, position):
if self.circle.collidepoint(position):
self.radius = self.radius // 2
else:
self.radius = self.radius * 2
self.draw()
def draw(self):
self.surface.fill(self.black)
self.circle = pygame.draw.circle(self.surface, self.color, self.center, self.radius)
Just calculate the distance between the center of the circle and the position of the mouse click:
x1, y1 = position
x2, y2 = self.circle.center
distance = math.hypot(x1 - x2, y1 - y2)
Then check if this distance is smaller or equal the radius of the circle:
if distance <= self.radius:
self.radius = self.radius // 2
...
When a click is detected, have the handler determine if it is actually inside the circle. Otherwise ignore it.

Pygame Rect, what are the arguments?

I know this may sound stupid, but the pygame documentation on their website says that it is:
x = pygame.Rect(left,top,width,height)
However, in my program, I cannot figure out if that is true, or if the arguments are actually two sets of coordinates. I'm not nearly experienced to find out by looking through the pygame source code.
Both of them work:
class pygame.Rect
pygame object for storing rectangular coordinates
Rect(left, top, width, height) -> Rect
Rect((left, top), (width, height)) -> Rect
Rect(object) -> Rect
So, if you have coordinates (x1, y1) and (x2, y2), both of the following would work:
pygame.Rect(x1, y1, x2-x1, y2-y1)
pygame.Rect((x1, y1), (x2-x1, y2-y1))

Cairo clip creates unwanted edges

I am using pyCairo for drawing moving elements on a surface.
In order to get better perfomance i tried to use "clip" function to redraw only the changed parts of a bigger image . Unfortunately it creates unwanted edges on the image. The edges of the cliping can be seen. Is it possible to avoid this kind of behaviour?
import math
import cairo
def draw_stuff(ctx):
""" clears background with solid black and then draws a circle"""
ctx.set_source_rgb (0, 0, 0) # Solid color
ctx.paint()
ctx.arc (0.5, 0.5, 0.5, 0, 2*math.pi)
ctx.set_source_rgb (0, 123, 0)
ctx.fill()
WIDTH, HEIGHT = 256, 256
surface = cairo.ImageSurface (cairo.FORMAT_ARGB32, WIDTH, HEIGHT)
ctx = cairo.Context (surface)
ctx.scale (WIDTH, HEIGHT) # Normalizing the canvas
draw_stuff(ctx)
#Let's draw stuff again, this time only redrawing a small part of the image
ctx.save()
ctx.rectangle(0.2,0.2,0.2,0.2)
ctx.clip()
draw_stuff(ctx)
ctx.restore()
surface.write_to_png ("example.png") # Output to PNG
You should round your cliping coordinates to integers (in device space). See http://cairographics.org/FAQ/#clipping_performance
I don't know the Python API and I am just guessing how it might work like from the C API, but it is something like this:
def snap_to_pixels(ctx, x, y):
x, y = ctx.user_to_device(x, y)
# No idea how to round an integer in python,
# this would be round() in C
# (Oh and perhaps you don't want this rounding, but
# instead want to round the top-left corner of your
# rectangle towards negative infinity and the bottom-right
# corner towards positive infinity. That way the rectangle
# would never become smaller to the rounding. But hopefully
# this example is enough to get the idea.
x = int(x + 0.5)
y = int(x + 0.5)
return ctx.device_to_user(x, y)
# Calculate the top-left and bottom-right corners of our rectangle
x1, y1 = 0.2, 0.2
x2, y2 = x1 + 0.2, y1 + 0.2
x1, y1 = snap_to_pixels(ctx, x1, y1)
x2, y2 = snap_to_pixels(ctx, x2, y2)
# Clip for this rectangle
ctx.rectangle(x1, y1, x2 - x1, y2 - y1)
ctx.clip()

Categories

Resources