How to tint a png image with an alpha channel? [duplicate] - python

This question already has answers here:
Is it possible to change sprite colours in Pygame?
(1 answer)
Trying to make sections of sprite change colour, but whole sprite changes instead
(1 answer)
Closed 2 years ago.
I'm trying to code the typical dvd bouncing screensaver. I am happy with it but I want to change the color of the logo everytime it hits the wall. I have used fill(), but the logo changes to a colored rectangle. I want to change the color of the logo, respecting the alpha channel of the image.
from pygame import *
import random
#set canvas size variables
width = 700
height = 450
#draw canvas
screen = display.set_mode((width,height))
display.set_caption('Graphics')
#initial XY coordinates where game starts
x = random.randint(1, width)
y = random.randint(1, height)
#import logo
logo_img = image.load('dvd_logo_alpha.png')
R = 255
G = 255
B = 255
def logo(x,y):
screen.blit(logo_img, (x,y))
def Col():
R = random.randint(100,255)
G = random.randint(100,255)
B = random.randint(100,255)
#speed of the logo
dx = 3
dy = 3
endProgram = False
while not endProgram:
for e in event.get():
if e.type == QUIT:
endProgram = True
#speed changes position XY
x += dx
y += dy
#detection of collision with border of screen
if y<0 or y>height-47:
dy *= -1
R = random.randint(100,255)
G = random.randint(100,255)
B = random.randint(100,255)
if x<0 or x>width-100:
dx *= -1
R = random.randint(100,255)
G = random.randint(100,255)
B = random.randint(100,255)
screen.fill((0))
logo_img.fill((R,G,B)) #here is the problem I can not solve
logo(x,y)
display.update()

First you have to create an image with an alpha channel, to make the transparent area of the png image invisible. Use pygame.Surface.convert_alpha() To create an surface with an alpha channel:
tintImage = image.convert_alpha()
To tint an image by pygame.Surface.fill(), the special_flags has too be set to BLEND_RGBA_MULT. This causes that the all the pixels of the image are multiplied by the color, rather then set by the color:
tintImage.fill((R, G, B, 255), None, BLEND_RGBA_MULT)
Note, since the image has to be tint by different colors, the original image has to be kept. Use the function logo to copy the image, and "tint" an "blit" the copy of the image:
def logo(x, y, color):
tintImage = logo_img.convert_alpha()
tintImage.fill((R, G, B, 255), None, BLEND_RGBA_MULT)
screen.blit(tintImage, (x, y))
Call the function in the main loop of the program:
endProgram = False
while not endProgram:
for e in event.get():
if e.type == QUIT:
endProgram = True
#speed changes position XY
x += dx
y += dy
#detection of collision with border of screen
if y<0 or y>height-47:
dy *= -1
R = random.randint(100,255)
G = random.randint(100,255)
B = random.randint(100,255)
if x<0 or x>width-100:
dx *= -1
R = random.randint(100,255)
G = random.randint(100,255)
B = random.randint(100,255)
screen.fill((0))
#logo_img.fill((R,G,B)) #here is the problem I can not solve
logo(x, y, (R, G, B))
display.update()

Related

Detect collision between textbox and circle in pygame

I'm trying to create a game in python where one can drag a textbox around the screen, but whenever it touches the borders of a circle around it, I want the loop to start over, but with a different text (by storing all text-strings in a list, but I'm not that far, yet). This is how far I have come:
import pygame
import ptext
pygame.init()
gameDisplay = pygame.display.set_mode((500, 500))
gameDisplay.fill((255,255,255))
x = 190
y = 230
a = 250
b = 250
text = "ExampleText 1."
def textbox(x,y):
ptext.draw(text, (x,y), color = (0,0,0))
def circle(a,b):
pygame.draw.circle(gameDisplay, (0,0,0), (250, 250), 210, 5)
done = False
while not done:
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
elif event.type == pygame.MOUSEMOTION:
if event.buttons[0]:
x += event.rel[0]
y += event.rel[1]
textbox(x,y)
circle(a,b)
pygame.display.flip()
pygame.quit()
quit()
Now I understand I will need to detect collision of the borders of my objects, but here I'm pretty lost. I tried to store the variables of my objects in rectangles and then produce another if statement that recognizes whether or not my objects collide (I used a print command because I haven't gotten to the actual command I want, yet), but that won't print anything and I'm sure I'm on the wrong path, but it is my best effort...
For that I have defined:
text_rect = pygame.Rect(x, y, 10, 30)
circle_rect = pygame.Rect(a,b, 300, 300)
and then in my loop:
if circle_rect.colliderect(text_rect):
print("COLLIDE")
Does anybody have any tip on a better way to define the objects and to create the function I want?
(Edit: Btw.: I'm not too concerned about the fact that when I drag my textbox, it leaves a print of the text, since that doesn't happen in my original script, but would be thankful if anyone knows why it does that in my current example.)
A rectangle has 4 corner points. If the rectangle is "smaller" then the circle (the diameter of the circle is greater than the diagonal of the rectangle), then the rectangle collides with the contour of a circle, if at least one point is out of the circle and at least one point is in the circle.
Define the rectangle and setup a list of the corner points. Further you've to know the radius of the circle:
w, h = 10, 30
rect = pygame.Rect(x, y, 10, 30)
corners = [rect.bottomleft, rect.bottomright, rect.topleft, rect.topright]
radius = 210
Calculate the Euclidean distance of each corner point to the center of the circle (a, b):
import math
dist = [math.sqrt((p[0]-a)**2 + (p[1]-b)**2) for p in corners]
Create to lists, one with the points in the circle (p_in) and one with the points out of the circle (p_out):
p_out = [i for i, d in enumerate(dist) if d > radius]
p_in = [i for i, d in enumerate(dist) if d < radius]
If both list contain any element, then the rectangle intersects the circle contour:
if any(p_in) and any(p_out):
print("COLLIDE")
If len(p_in) is 4, then the rectangle is completely in the circle. If len(p_out) is 4 then the rectangle is completely out of the circle.
if any(p_in) and any(p_out):
print("COLLIDE")
elif len(p_in) == 4:
print("IN")
elif len(p_out) == 4:
print("OUT")
See the simple example, which is based on your code snippet and demonstrates the collision test. The rectangle is attached to the mouse:
import pygame
import math
pygame.init()
gameDisplay = pygame.display.set_mode((500, 500))
done = False
while not done:
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
x, y = pygame.mouse.get_pos()
w, h = 10, 30
rect = pygame.Rect(x, y, 10, 30)
a, b = 250, 250
radius = 210
corners = [rect.bottomleft, rect.bottomright, rect.topleft, rect.topright]
dist = [math.sqrt((p[0]-a)**2 + (p[1]-b)**2) for p in corners]
p_out = [i for i, d in enumerate(dist) if d > radius]
p_in = [i for i, d in enumerate(dist) if d < radius]
if any(p_in) and any(p_out):
print("COLLIDE")
elif len(p_in) == 4:
print("IN")
elif len(p_out) == 4:
print("OUT")
gameDisplay.fill((255,255,255))
pygame.draw.rect(gameDisplay, (255, 0, 0), rect)
pygame.draw.circle(gameDisplay, (0,0,0), (a, b), radius, 5)
pygame.display.flip()
pygame.quit()
quit()

How to create a taken damage / red vignette effect in pygame [duplicate]

This question already has answers here:
Changing ememy's color to show that it is aking damage?
(1 answer)
Is it possible to change sprite colours in Pygame?
(1 answer)
Changing colour of a surface without overwriting transparency
(1 answer)
Closed 2 years ago.
I'm making a 2D game in python using the module pygame. I would like to create a red vignette/bleed effect whenever the player takes damage in my game. This is seen in many games today, where the edges of the screen will flash red for a second and quickly disappear.
I have tried blitting an image I made in photoshop and scaling it accordingly during an animation cycle, but this was a really performance heavy operation, subsequently causing a lot of lag. I'm looking for alternatives to this method.
Code declaring a few variables:
bgX = 0
bgY = 0
damage = pygame.image.load("defensiveGameHUD.png").convert_alpha()
dimensions = [1920,1080]
Then I have this in the main loop of my game:
win.blit(background,(0,0))
if dimensions[0] != 4020:
dimensions[0] += 30
bgX -= 15
if dimensions[1] != 4600:
dimensions[1] += 40
bgY -= 20
if dimensions[1] != 4600:
screenDamage = pygame.transform.scale(damage, dimensions)
win.blit(screenDamage, (bgX, bgY))
else:
screenDamage = None
That is simply an animation that will scale the image in, however, the scaling is improper and this is very costly on performance.
def smmothstep(edge0, edge1, x):
t = min(1, max(0, (x - edge0) / (edge1 - edge0)))
return t * t * (3.0 - 2.0 * t)
def gen_damage_image(scale, source):
dest = source.copy()
img_size = dest.get_size()
for i in range(img_size[0]):
for j in range(img_size[1]):
fx = smmothstep(0, img_size[0]/2*scale, min(i, img_size[0]-i))
fy = smmothstep(0, img_size[1]/2*scale, min(j, img_size[1]-j))
color = dest.get_at((i, j))
fade_color = [int(255 - (1-fx*fy)*(255 - c)) for c in color]
dest.set_at((i, j), fade_color)
return dest
def tintDamage(surface, scale):
i = min(len(dmg_list)-1, max(0, int(scale*(len(dmg_list)-0.5))))
c.blit(dmg_list[i], (0, 0), special_flags = pygame.BLEND_MULT)
damage = pygame.image.load("defensiveGameHUD.png").convert_alpha()
max_dmg_img = 10
dmg_list = [gen_damage_image((i+1)/max_dmg_img, damage) for i in range(max_dmg_img)]
start_time = 0
tint = 0
damage_effect = False
To tint the screen in red can be achieved by pygame.Surface.fill(), by setting special_flags = BLEND_MULT.
The following function "tints" the entire surface in red, by a scale from 0 to 1. If scale is 0, the surface is not tinted and if scale is 1 the entire surface is tinted by the (red) color (255, 0, 0):
def tintDamage(surface, scale):
GB = min(255, max(0, round(255 * (1-scale))))
surface.fill((255, GB, GB), special_flags = pygame.BLEND_MULT)
The function has to be called right before pygame.display.flip() or pygame.display.update():
e.g.
tintDamage(win, 0.5)
pygame.display.flip()
Note, the special_flags = BLEND_MULT can also be set when using pygame.Surface.blit():
win.blit(damage, (bgX, bgY), special_flags = pygame.BLEND_MULT)
Or even both effects can be combined.
That's not exactly the effect I was looking for [...] I would like this effect to sort of scale itself inwards and then outwards, ...
What you want to do is tricky, because you would have to change each pixel of the damage surface dynamically. That would be much to slow.
But you can precalculate different damage surfaces, depending on an effect scale:
def smmothstep(edge0, edge1, x):
t = min(1, max(0, (x - edge0) / (edge1 - edge0)))
return t * t * (3.0 - 2.0 * t)
def gen_damage_image(scale, source):
dest = source.copy()
img_size = dest.get_size()
for i in range(img_size[0]):
for j in range(img_size[1]):
fx = smmothstep(0, img_size[0]/2*scale, min(i, img_size[0]-i))
fy = smmothstep(0, img_size[1]/2*scale, min(j, img_size[1]-j))
color = dest.get_at((i, j))
fade_color = [int(255 - (1-fx*fy)*(255 - c)) for c in color]
dest.set_at((i, j), fade_color)
return dest
damage = pygame.image.load("defensiveGameHUD.png").convert_alpha()
max_dmg_img = 10
dmg_list = [gen_damage_image((i+1)/max_dmg_img, damage) for i in range(max_dmg_img)]
tintDamage choose a damage image of the list, dependent on the scale:
def tintDamage(surface, scale):
i = min(len(dmg_list)-1, max(0, int(scale*(len(dmg_list)-0.5))))
c.blit(dmg_list[i], (0, 0), special_flags = pygame.BLEND_MULT)
The inwards / outwards effect can be achieved by a sine function. See the example, which starts the effect when x is pressed:
run = True
start_time = 0
tint = 0
damage_effect = False
while run:
clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_x:
damage_effect = True
tint = 0
win.fill((196, 196, 196))
# [...]
if damage_effect:
scale = math.sin(tint)
tintDamage(win, scale)
tint += 0.1
damage_effect = scale >= 0
pygame.display.flip()
Since the computation of the images is very slow, I provide a solution, which generated a scale mask on a 20x20 image. The mask is scaled to the size of the damage image and blended with the damage image:
def gen_damage_image(scale, source):
scale_size = (20, 20)
scale_img = pygame.Surface(scale_size, flags = pygame.SRCALPHA)
for i in range(scale_size[0]):
for j in range(scale_size[1]):
fx = smmothstep(0, scale_size[0]/2*scale, min(i, scale_size[0]-i))
fy = smmothstep(0, scale_size[1]/2*scale, min(j, scale_size[1]-j))
fade_color = [int(max(0, 255 - (1-fx*fy)*255)) for c in range(4)]
scale_img.set_at((i, j), fade_color)
dest = source.copy()
scale_img = pygame.transform.smoothscale(scale_img, dest.get_size())
dest.blit(scale_img, (0, 0), special_flags = pygame.BLEND_ADD)
return dest

Collisions in Zelle graphics.py

I am trying to make my circle bounce off of my rectangle using Zelle graphics.py. Once the circle bounces off of the rectangle I wanted it to keep moving randomly. Here is my code so far, and it's working!
Also I know that each circle graphics technically can use the points of the smallest possible square that would fit around the circle to do the collision but I'm having trouble with doing that.
from graphics import *
import random
def delay(d):
for i in range(d):
for i in range(50):
pass
#-------------------------------------------------
def main():
win=GraphWin("Moving Circle",500,400)
win.setBackground('white')
pt= Point(100,200)
cir=Circle(pt,30)
#changes the color of the circle for each game
r = random.randrange(256)
b = random.randrange(256)
g = random.randrange(256)
color = color_rgb(r, g, b)
cir.setFill(color)
cir.draw(win)
#rectangle
rec = Rectangle(Point(450,450), Point(275, 425))
rec.draw(win)
rec.setFill('black')
#-------------------------------------------------
pt5 = Point(250,30)
instruct1=Text(pt5, "click multiple times to start(rectangle can take multiple clicks to move)")
instruct1.setTextColor('black')
instruct1.draw(win)
#-------------------------------------------------
p=cir.getCenter()
p2=win.getMouse()
dx=1
dy=1
keepGoing=True
while keepGoing:
d = 100
delay(d)
cir.move(dx,dy)
p=cir.getCenter()
p2=win.checkMouse()
instruct1.setText("")
#rectanlge
isClicked= win.checkMouse()
if isClicked:
rp = isClicked
rc = rec.getCenter()
rdx = rp.getX() - rc.getX()
rdy = rp.getY() - rc.getY()
rec.move(rdx,rdy)
#circle
if((p.getX()-30)<=0.0) or ((p.getX()+30)>=500):
dx= -dx
if((p.getY()-30)<=0.0) or ((p.getY()+30)>=400):
dy=-dy
p3=win.checkMouse()
main()
I know that each circle graphics technically can use the points of the
smallest possible square that would fir around the circle to do the
collision
I'm playing with an alternate idea -- we could consider a circle around the rectangle instead of a square around the circle. The issue for me is that we not only need to detect collision, but come out with a sense of which way to move away from the other object. It's not just True and False but rather a (dx, dy) type of result.
Obviously, a circle around the rectangle is too crude, but suppose it were lots of smaller circles making up the rectangle and we measure circle center to center distance to detect a hit:
A hit on just a central (green) rectangle circle means reverse the vertical direction of the big circle. A hit on just the end (red) circle means reverse the horizontal direction of the big circle. And we can detect both kinds of hits and reverse the big circle completely.
Here's my rework of your code with the above in mind -- I also fixed your multiple clicking issue and made lots of style changes:
from random import randrange
from graphics import *
WIDTH, HEIGHT = 500, 400
RADIUS = 30
def delay(d):
for _ in range(d):
for _ in range(50):
pass
def distance(p1, p2):
return ((p2.getX() - p1.getX()) ** 2 + (p2.getY() - p1.getY()) ** 2) ** 0.5
def intersects(circle, rectangle):
dx, dy = 1, 1 # no change
center = circle.getCenter()
rectangle_radius = (rectangle.p2.getY() - rectangle.p1.getY()) / 2
rectangle_width = rectangle.p2.getX() - rectangle.p1.getX()
y = rectangle.getCenter().getY()
for x in range(int(rectangle_radius * 2), int(rectangle_width - rectangle_radius * 2) + 1, int(rectangle_radius)):
if distance(center, Point(rectangle.p1.getX() + x, y)) <= rectangle_radius + RADIUS:
dy = -dy # reverse vertical
break
if distance(center, Point(rectangle.p1.getX() + rectangle_radius, y)) <= rectangle_radius + RADIUS:
dx = -dx # reverse horizontal
elif distance(center, Point(rectangle.p2.getX() - rectangle_radius, y)) <= rectangle_radius + RADIUS:
dx = -dx # reverse horizontal
return (dx, dy)
def main():
win = GraphWin("Moving Circle", WIDTH, HEIGHT)
circle = Circle(Point(WIDTH / 5, HEIGHT / 2), RADIUS)
# change the color of the circle for each game
color = color_rgb(randrange(256), randrange(256), randrange(256))
circle.setFill(color)
circle.draw(win)
# rectangle
rectangle = Rectangle(Point(275, 425), Point(450, 450)) # off screen
rectangle.setFill('black')
rectangle.draw(win)
dx, dy = 1, 1
while True:
delay(100)
circle.move(dx, dy)
# rectangle
isClicked = win.checkMouse()
if isClicked:
point = isClicked
center = rectangle.getCenter()
rectangle.move(point.getX() - center.getX(), point.getY() - center.getY())
# circle
center = circle.getCenter()
if (center.getX() - RADIUS) <= 0.0 or (center.getX() + RADIUS) >= WIDTH:
dx = -dx
if (center.getY() - RADIUS) <= 0.0 or (center.getY() + RADIUS) >= HEIGHT:
dy = -dy
# collision bounce
x, y = intersects(circle, rectangle)
dx *= x
dy *= y
main()
Not perfect, but something to play around with, possibly plugging in a better intersects() implementation.

random circles using SimpleGraphics

I need to make a circle by adjusting conditions on the heights, this program using a lot of random circles but I am unsure where to go from here? I am trying to use the following equation d = (sqrt)((x1 –x2)^2 +(y1 – y2)^2). Right now the program draws many random circles, so adjusting the formula i should be able to manipulate it so that certain circles are red in the centre (like the japan flag).
# using the SimpleGraphics library
from SimpleGraphics import *
# use the random library to generate random numbers
import random
diameter = 15
##
# returns a valid colour based on the input coordinates
#
# #param x is an x-coordinate
# #param y is a y-coordinate
# #return a colour based on the input x,y values for the given flag
##
def define_colour(x,y):
##
if y < (((2.5 - 0)**2) + ((-0.5 - 0)**2)**(1/2)):
c = 'red'
else:
c = 'white'
return c
return None
# repeat until window is closed
while not closed():
# generate random x and y values
x = random.randint(0, getWidth())
y = random.randint(0, getHeight())
# set colour for current circle
setFill( define_colour(x,y) )
# draw the current circle
ellipse(x, y, diameter, diameter)
Here's some code that endlessly draws circles. Circles that are close to the centre of the screen will be drawn in red, all other circles will be drawn in white. Eventually, this will create an image similar to the flag of Japan, although the edge of the inner red "circle" will not be smooth.
I have not tested this code because I don't have the SimpleGraphics module, and I'm not having much success locating it via Google or pip.
from SimpleGraphics import *
import random
diameter = 15
width, height = getWidth(), getHeight()
cx, cy = width // 2, height // 2
# Adjust the multiplier (10) to control the size of the central red portion
min_dist_squared = (10 * diameter) ** 2
def define_colour(x, y):
#Calculate distance squared from screen centre
r2 = (x - cx) ** 2 + (y - cy) ** 2
if r2 <= min_dist_squared:
return 'red'
else:
return 'white'
# repeat until window is closed
while not closed():
# generate random x and y values
x = random.randrange(0, width)
y = random.randrange(0, height)
# set colour for current circle
setFill(define_colour(x, y))
# draw the current circle
ellipse(x, y, diameter, diameter)

Creating a (R,G,B) Sierpinski Triangle in python, using pygame window. Each corner is, respectively Red, Green, and Blue and gradient into each other

So, for my computer science class we are supposed to import the pygame from the website:
http://www.petercollingridge.co.uk/image-processing-pygame
Then we are supposed to create the sierpinski triangle in python in the pygame window using pixels. So each pixel in the window needs to be colored in the shape of the triangle. I can't even get my triangle to show up in just black pixels, and what we're supposed to do is get it to appear with the top corner as red, the bottom left as green, and the bottom right as blue. These colors are supposed to slowly fade into each other (gradient) throughout the triangle. The finished process is supposed to look something like this:
http://eldar.mathstat.uoguelph.ca/dashlock/ftax/Gallery/Sierpenski2D960.gif
First off, everytime I set the window up it says that the midPoint in my main function, where I call the earlier midPoint function is not assigned. This confuses me because I clearly assigned it in the very first function: def midPoint, so any help with that problem would be great. Other than that I'm not sure why I can't get the actual triangle to show up. I just want to start out by getting it to show up black first, and then color it. Any help on what is wrong with my, most likely, awful code would be much appreciated. I am supposed to be minoring in computer science but I am failing the class. I am desperate. Please you can even make fun of my shitty code but I need something, anything. I'm lost. Thank you.
#######################################
import pygame, math, random
pygame.init()
#######################################
def midpoint (x0, x1, y0, y1):
panda = ((x0 + x1)/2)
polarbear = ((y0 + y1)/2)
return panda, polarbear
#######################################
def randomPoint (width, height):
potato = (random.random() * width)
pickle = (random.random() * height)
return potato, pickle
#newImage
# PRE: Takes size, which is a 2-tuple (width, height) and provides size of image
# POST: Creates list of length size[0]. Each item in list is length size[1]. Each item of list is a 3-tuple.
#
# Points of this data structure are denoted as image[x][y] and each point has 3 components: [0] for red, [1] for green, and [2] for blue
#
def newImage(size):
return pygame.surfarray.array3d(pygame.Surface(size))
#######################################
#showImage
# Takes image created by newImage and displays it in open window
# PRE: image is a list of lists of 3-tuples. Each 3 tuple corresponds to a (R,G,B) color.
# POST: image is displayed in window.
#
def showImage(image):
width, height, depth = image.shape
pygame.display.set_mode((width, height))
surface = pygame.display.get_surface()
pygame.surfarray.blit_array(surface, image)
pygame.display.flip()
#######################################
# MAIN PROGRAM
pygame.init()
width = int(input("How large do you want your window? "))
height = int(input("How tall do you want your window? "))
window = newImage((width, height))
for x in range(width):
for y in range(height):
window[x][y] = (255,255,255) #Colors window white
showImage(window)
#
p = randomPoint(width, height)
for i in range(1000001):
corners = [(width, height),(0, height),(width//2, 0)]
c = random.choice(corners)
mid = midPoint(p[0], p[1], c[0], c[1])
if i > 10:
window[(mid[0])][(mid[1])] = (0,0,0)
p = mid
if i % 1000 == 0:
showImage(window)
#
print('Done!')
input("Enter to quit")
pygame.quit()
#
#######################################`
###################SIERPINSKI TRIANGLE (R,G,B)###################
###########################
###################
##########
#######################################
import pygame, math, random
pygame.init()
#######################################
#newImage
# PRE: takes a 2-tuple (width, height) input from user and provides size of image
# POST: Creates list, len[0]. Each item in list is len[1]. Each item is 3-tuple.
# Points of data structure (pixels) are denoted as image[x][y] and each point has 3 components:
##########################################################################################
[0] - RED
##########################################################################################
[1] - GREEN
##########################################################################################
[2] - BLUE
def newImage(size):
return pygame.surfarray.array3d(pygame.Surface(size))
#######################################
#showImage
# Main function: Takes image created by "newImage" and displays it in pygame window
# PRE: image is a LIST OF LISTS of 3-tuples. Each 3 of the tuples corresponds to a (R,G,B) color.
# POST: image is displayed in window
def showImage(image):
width, height, depth = image.shape
pygame.display.set_mode((width, height))
surface = pygame.display.get_surface()
pygame.surfarray.blit_array(surface, image)
pygame.display.flip()
#######################################
#randomPoint
# set the variable "p" in main function to the returned values of this function which should be a random point
# PRE: takes in 2-tuple (width, height)
# POST: returns coordinates of a random point in the size of the image
def randomPoint(width, height):
ex = (random.random() * width)
wye = (random.random() * height)
return ex, wye
#######################################
#midPoint
# find the mid-point between "p" - random point and "c" - random corner in the main function
# PRE: take in all 4 coordinates of the 2 points
# POST: calculate the mid-point between these 2 points and color it black. Set p to the midPoint once this function is complete and repeat.
def midPoint(x0, y0, x1, y1):
eks = ((x0 + x1)/2)
wie = ((y0 + y1)/2)
return eks, wie
#######################################
def colorPoint (x, y, width, height):
w = (255/width)
h = (255/height)
x_color = x*w
y_color = y*h
r = math.fabs(255 - y_color)
g = math.fabs(255 - x_color)
b = math.fabs(255 - x_color - y_color)
return r, g, b
showImage(window)
#######################################
# MAIN PROGRAM
# Start the CHAOS GAME
pygame.init()
#######################################
# Get user input for the width and height of the window
width = int(input("How wide would you like your window to be? "))
height = int(input("How tall would you like your window to be? "))
window = newImage((width, height))
for ecks in range(width):
for why in range(height):
window[ecks][why] = (255,255,255) #Colors window white
showImage(window)
#######################################
# Set "p" to starting value
p = 1
# Call randomPoint in order to set "p" to a random point within the parameters of the window size
p = randomPoint(width, height)
i = 0
for i in range(1000001):
corners = [(width, height),(0, height),(width//2, 0)]
c = random.choice(corners)
mid = midPoint(p[0], p[1], c[0], c[1])
colour = colorPoint((mid[0]), (mid[1]), width, height)
if i > 10:
window[(mid[0])][(mid[1])] = colour
i += 1
p = mid
if i % 1000 == 0:
showImage(window)
#######################################
#End the CHAOS GAME
print ('Done!')
input ("ENTER to quit")
pygame.quit()
#######################################

Categories