Does anyone know of an easy way to draw ellipses that are not aligned to the x & y axis. I am very new to pygame so please forgive my ignorance, but I cannot find anything related to it.
If no easy method exists, can someone help me in how I might draw this besides generating many many points on the ellipse and plotting all of them?
You can do that. Create a surface, draw the ellipse onto that surface and then rotate the entire surface (with the ellipse on it). Here's my test code:
import pygame, sys
screen = pygame.display.set_mode((1024, 640))
running = True
#let's create a surface to hold our ellipse:
surface = pygame.Surface((320, 240))
red = (180, 50, 50)
size = (0, 0, 300, 200)
#drawing an ellipse onto the
ellipse = pygame.draw.ellipse(surface, red, size)
#new surface variable for clarity (could use our existing though)
#we use the pygame.transform module to rotate the original surface by 45°
surface2 = pygame.transform.rotate(surface, 45)
while running:
screen.fill((255, 250, 200))
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
screen.blit(surface2, (100, 100))
pygame.display.update()
The result will be a rotated ellipse. It would be possible to make the "holder" of the ellipse transparent. Check the documentations on the modules:
http://www.pygame.org/docs/ref/transform.html#pygame.transform.rotate
http://www.pygame.org/docs/ref/surface.html
Hope that helps!
If anyone is curious how to draw a "flower" using rotated ellipses, the following might help with that.
def flower(width: int, color: tuple, edges: bool=False):
W, H = width, width
# create a flower surface with an alpha channel on which to draw
# the petals
flower = pygame.Surface((W, H), pygame.SRCALPHA, 32).convert_alpha()
R = flower.get_rect()
cx, cy = R.center
# assuming petal height should be half their width
petal_size = (width//2, width//4)
pw, ph = petal_size
radius = pw/2
center_radius = width//10
center_color = (255-color[0], 255-color[1], 255-color[2])
def draw_petal(S, x, y, w, h, angle):
# Create surface for drawing an individual petal
surface = pygame.Surface((w, h), pygame.SRCALPHA, 32).convert_alpha()
# Draw the un-rotated petal
pygame.draw.ellipse(surface, color, (0, 0, w, h), 0)
if edges:
pygame.draw.ellipse(surface, BLACK, (0, 0, w, h), 1)
# Create a new surface with the petal rotated by angle
rot_surface = pygame.transform.rotate(surface, angle)
# Need center of rotated surface to blit (draw) the rotated
# petal at the given (x, y) coordinate
rcx, rcy = rot_surface.get_rect().center
# Draw the center of the rotated petal at (x, y)
S.blit(rot_surface, (x - rcx, y - rcy))
# Petals are drawn at diagonals first, then the horizontal petals,
# then the vertical petals
angles = [
45, 135, 225, 315, # diagonals
0, 180, # horizontal
90, 270 # vertical
]
for a in angles:
# placing petal centers onto circle of radius (petal_width/2)
x, y = map(int, (
radius*math.cos(math.radians(a)), radius*math.sin(math.radians(a))
))
draw_petal(flower, cx+x, cy+y, pw, ph, -a)
# draw flower center (don't remember what it's called)
pygame.draw.circle(flower, center_color, (cx, cx), center_radius)
if edges:
pygame.draw.circle(flower, BLACK, (cx, cx), center_radius, 1)
def draw_flower(S, x, y, flower=flower):
S.blit(flower, (x - cx, y - cy))
return draw_flower
To use this code:
import math
import pygame
BLACK = ( 0, 0, 0)
GREEN = ( 0, 255, 0)
RED = ( 255, 0, 0)
pygame.init()
size = (800, 800)
SW, SH = size
screen = pygame.display.set_mode(size)
pygame.display.set_caption("Flower Demo")
done = False
clock = pygame.time.Clock()
# insert above flower code
draw_green_flower = flower(100, GREEN)
draw_red_flower = flower(100, RED)
try:
while not done:
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
done = True
screen.fill(WHITE)
draw_green_flower(screen, SW/2,SH/2)
draw_red_flower(screen, SW/2-100,SH/2-100)
pygame.display.flip()
clock.tick(60)
finally:
pygame.quit()
In case this helps someone, I wrote a function that lets you draw an ellipse between any two points A and B.
Not the most elegant math but it works! See example below:
import pygame
import math
def draw_ellipse(A, B, width, color, line):
"""
draws ellipse between two points
A = start point (x,y)
B = end point (x,y)
width in pixel
color (r,g,b)
line thickness int, if line=0 fill ellipse
"""
# point coordinates
xA, yA = A[0], A[1]
xB, yB = B[0], B[1]
# calculate ellipse height, distance between A and B
AB = math.sqrt((xB - xA)**2 + (yB - yA)**2)
# difference between corner point coord and ellipse endpoint
def sp(theta):
return abs((width / 2 * math.sin(math.radians(theta))))
def cp(theta):
return abs((width / 2 * math.cos(math.radians(theta))))
if xB >= xA and yB < yA:
# NE quadrant
theta = math.degrees(math.asin((yA - yB) / AB))
xP = int(xA - sp(theta))
yP = int(yB - cp(theta))
elif xB < xA and yB <= yA:
# NW
theta = math.degrees(math.asin((yB - yA) / AB))
xP = int(xB - sp(theta))
yP = int(yB - cp(theta))
elif xB <= xA and yB > yA:
# SW
theta = math.degrees(math.asin((yB - yA) / AB))
xP = int(xB - sp(theta))
yP = int(yA - cp(theta))
else:
# SE
theta = math.degrees(math.asin((yA - yB) / AB))
xP = int(xA - sp(theta))
yP = int(yA - cp(theta))
# create surface for ellipse
ellipse_surface = pygame.Surface((AB, width), pygame.SRCALPHA)
# draw surface onto ellipse
pygame.draw.ellipse(ellipse_surface, color, (0, 0, AB, width), line)
# rotate ellipse
ellipse = pygame.transform.rotate(ellipse_surface, theta)
# blit ellipse onto screen
screen.blit(ellipse, (xP, yP))
screen = pygame.display.set_mode((1000, 1000))
running = True
while running:
screen.fill((255, 250, 200))
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
draw_ellipse((500, 500), (420, 350), 100, (0, 255, 0), 5)
draw_ellipse((400, 600), (700, 280), 80, (255, 0, 0), 5)
draw_ellipse((260, 190), (670, 440), 50, (0, 0, 255), 5)
pygame.display.update()
Unfortunately, there is no direct way to draw a rotated shape. pygame.transform.rotate()
can rotate a pygame.Surface
object but you cannot rotate a shape directly. You need to draw the shape on a Surface and rotate that Surface :
pygame.Surface
object with a per-pixel alpha format and with the size of the shape.blit
the Surface with the shapeonto the target Surface . Write a functions that draws the rotated shapes:
def draw_ellipse_angle(surface, color, rect, angle, width=0):
target_rect = pygame.Rect(rect)
shape_surf = pygame.Surface(target_rect.size, pygame.SRCALPHA)
pygame.draw.ellipse(shape_surf, color, (0, 0, *target_rect.size), width)
rotated_surf = pygame.transform.rotate(shape_surf, angle)
surface.blit(rotated_surf, rotated_surf.get_rect(center = target_rect.center))
Minimal example:
import pygame
def draw_ellipse_angle(surface, color, rect, angle, width=0):
target_rect = pygame.Rect(rect)
shape_surf = pygame.Surface(target_rect.size, pygame.SRCALPHA)
pygame.draw.ellipse(shape_surf, color, (0, 0, *target_rect.size), width)
rotated_surf = pygame.transform.rotate(shape_surf, angle)
surface.blit(rotated_surf, rotated_surf.get_rect(center = target_rect.center))
pygame.init()
window = pygame.display.set_mode((250, 250))
clock = pygame.time.Clock()
background = pygame.Surface(window.get_size())
ts, w, h, c1, c2 = 50, *window.get_size(), (160, 160, 160), (192, 192, 192)
tiles = [((x*ts, y*ts, ts, ts), c1 if (x+y) % 2 == 0 else c2) for x in range((w+ts-1)//ts) for y in range((h+ts-1)//ts)]
for rect, color in tiles:
pygame.draw.rect(background, color, rect)
angle = 0
run = True
while run:
clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
window.blit(background, (0, 0))
draw_ellipse_angle(window, (0, 0, 255), (25, 75, 200, 100), angle, 5)
angle += 1
pygame.display.flip()
pygame.quit()
exit()
I do not know python or pygame, but depending on what you are building, it may be easier to just make an image using a program like inkscape for pc and mac, or inkpad for iPad. Both of these let you make a diagonal ellipse, and then export it as a .png and use it in your code. Again, if this is possible really depends on what you are doing with the ellipse.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.