playing with trigonometry sin in pygame
Ok I am so far from understanding, so don't take this as any kind of math lesson.
Also, every time I thought I knew what I was doing.... pygame would show me differently. Still a work in progress, but for now, something to play with.
Update: SinWaveTime class added to produce that particular weaving effect
Tinkering with the different sin wave variables:
I wrote this piece separate from my 3D experiment to see how to manipulate the sin wave.
While trying to use time as the factor to move my pygame draw circle on the x-axis, i got this crazy little doo-dad :
I don't think it's drawing two circles at once, but if I figure out what the heck it's doing I'll let you know. Or hey if you know, drop a comment. I don't know if my comments are just not working, or no one wants to.
So, here's some pygame code to play with the sin wave. Alter the different variables to see it in action.
picture of SinWave.move_with_time()
see changes, SinWaveTime class set up to specifically produce this effect
picture of SinWave.move_point2()
picture of SinWave.move_point():
code:
There are a ton of comment in the code. It helps me remember, and my guess is they're helpful to learners like me. *or people who just go: "What the hell was she thinking!?"*
#!usr/bin/python3
# -*- coding: utf-8 -*-
import pygame as pg
import math
from sys import exit
class SkullGlobals(object):
""" class container for globally used variables """
def __init__(self):
self.WIDTH = 600
self.HEIGHT = 600
self.background_color = (130, 120, 100)
self.SAND = (130, 120, 100)
self.BLUE = (40, 60, 200)
self.LBLUE = (100, 100, 255)
self.RED = (230, 50, 50)
self.GREEN = (50, 230, 50)
self.D_WHITE = (200,200,200)
self.CENTER = (self.WIDTH//2, self.HEIGHT//2)
self.FULL_SIZE = (self.WIDTH//4 + self.HEIGHT//4)//2
self.SMALL_SIZE = (self.WIDTH//50 + self.HEIGHT//50)//2
self.base_color = 150
class SinWave(object):
def __init__(self, screen, globals):
self.screen = screen
self.globals = globals
self.x_pos = 0
self.max_x = self.globals.WIDTH
self.start_y_pos = self.globals.HEIGHT
self.y_pos = self.globals.HEIGHT
self.max_y = self.globals.HEIGHT
self.step = .015 # nice sharp 0.2 with 0.03 step
self.blue = 228
self.red = 10
self.green = 10
self.move = 11
def move_point2(self):
"""This was made to introduce a second wave with different parameters
"""
frequency = 0.3 # less frequency less wave intensity
self.x_pos += 2 # increases breadth of wave
# point position = pp
pp_y = self.y_pos
# smaller amp = more solid, small decent waves
amplitude = 10 # amp higher is taller
# sine wave formula = swf
swf = int(-1 * math.sin(self.step * frequency) * amplitude)
if self.x_pos < self.max_x:
self.x_pos += 1 # speed? Most formulas use time for the x position
# if change in step is not = original step, y position changes
self.step += 0.3
else:
# reset step, x_pos, move y axis up/down screen
self.step = 0.03
self.x_pos = 0
self.move += 1
# moving y upscreen:
self.y_pos -= self.move
if self.move > 10:
self.move = 2
if self.y_pos > -400:
self.y_pos = self.y_pos + swf
else:
# wave out of screen parameters
self.y_pos = self.start_y_pos
if self.blue <= 100:
self.blue += 15
elif self.blue > 100 and self.blue < 240:
self.blue += 10
else:
self.blue = 0
if self.green <= 100:
self.green += 15
elif self.green < 240 and self.blue > 100:
self.green += 10
else:
self.green = 0
#changes here override color changes in above else:
# they are happening on every circle draw
if self.red <= 50:
self.red += 2
if self.red <= 150:
self.red += 1
if self.red > 150 and self.red >= 50:
self.red -= 3
def move_point(self):
""" First play around with altering sin wave
color change is extremely gradual
y's position is changed in separate if/else clause.
x position is change constant. x+= 1 """
frequency = 0.3 # less frequency less wave intensity
# smaller amp = more solid, small decent waves
amplitude = 10 # amp higher is taller
# sine wave formula = swf
swf = int(-1 * math.sin(self.step * frequency) * amplitude)
if self.x_pos < self.max_x:
self.x_pos += 1
self.step += 0.15
# if change in step is not = original step, y position changes
else:
# reset step, x_pos, move y axis up/down screen
self.step = 0.03
self.x_pos = 0
self.y_pos -= self.move
if self.y_pos > -300:
self.y_pos = self.y_pos + swf
else:
self.y_pos = self.start_y_pos
if self.green < 50:
self.green += 10
elif self.green < 150:
self.green += 15
elif self.green < 240:
self.green += 5
else:
self.green = 0
if self.blue <= 50:
self.blue += 175
if self.blue >= 150:
self.blue -= 1
if self.blue >= 225:
self.blue -= 1
def move_with_time(self):
"""
A couple of the original pieces I found online said to
use time to change the x coordinate.
That'll be this one, with just a white circle.
It'll be set up to not alter where y draws the circle
except for the sin wave
I got some really fun results tinkering with this
"""
# define a frequency and amplitude:
# if either of these ends up 0, swf will = 0
amplitude = 20
frequency = 10
##############################
# cool little weavy pattern:
#frequency = 4
#amplitude = 40
#step = 0.027
#self.y_pos = self.globals.HEIGHT//2
#####################################
# set up y position to middle of screen
self.y_pos = self.globals.HEIGHT//2
#http://pygametutorials.wikidot.com/book-time
# pygame.time is measured in 1/1000 of a second
#time = (pg.time.get_ticks())//1000
# the above gradually increases, so wave speeds up visually
# it is not a constant range
time = (pg.time.get_ticks()//1000)
# modulate:
# modulating will mean the distance between x points
# can be 0 - 3, as below
# at 0 x does not move, stalling the movement across x
# so I took that out with the little if below
time = time % 3
if time == 0:
time += 1
# sin formula:
swf = int(-1 * math.sin(self.step * frequency) * amplitude)
# set the changes
if self.x_pos < self.max_x:
self.x_pos = self.x_pos + time
self.y_pos = self.y_pos + swf
# weavy step:
#self.step += 0.27
self.step += 0.3
else:
# reset step, x_pos, move y axis up/down screen
# I'm not sure if resetting the step is necessary
# it seems step can reach to infinite without messing too much
# with the wave
# still need more research on trigonometry
black = (0, 0, 0)
self.screen.fill(black)
#weavy step:
#self.step = 0.027
self.step = 0.3
self.x_pos = 0
self.y_pos = self.start_y_pos
def draw_point(self, second=False, third=False):
""" Activate movement, draw circle accordingly """
# set a color and radius, change as desired
radius = 15
# setting the color this way allows me to change it in the movement method
color = (self.red, self.green, self.blue)
# I like to dull the colors a smidge so it doesn't scream at my eyeballs
# full white is (255, 255, 255)
white = (230, 230, 230)
# I'm sure there's a better way to do the part below
# trying to make sure with each call, it only grabs one of the methods
# Or None if they try to draw more then one with a call to it.
if second == False and third == False:
pg.draw.circle(self.screen, color, (self.x_pos, self.y_pos), radius, 0)
self.move_point()
if second == True and third == False:
radius = 10
pg.draw.circle(self.screen, color, (self.x_pos, self.y_pos), radius, 0)
self.move_point2()
if third == True and second == False:
radius = 10
# fill screen to watch circle only
#black = (0, 0, 0)
#self.screen.fill(black)
pg.draw.circle(self.screen, white, (self.x_pos, self.y_pos), radius, 0)
self.move_with_time()
####### SinWaveTime --- weaving pattern #########
####### cleared out comments, I only changed a little bit##
class SinWaveTime(object):
""" Separate SinWave container for time alterations
this one stays center screen, so the other class interferes
with translation when you try to set it to center on each call"""
def __init__(self, screen, globals):
self.screen = screen
self.globals = globals
self.x_pos = 0
self.max_x = self.globals.WIDTH
self.start_y_pos = self.globals.HEIGHT//2 # <--- changed
self.y_pos = self.globals.HEIGHT//2 #<---- changed
self.max_y = self.globals.HEIGHT
self.center = self.globals.HEIGHT // 2
self.step = 0.027 # nice sharp 0.2 with 0.03 step
self.blue = 228
self.red = 10
self.green = 10
self.move = 11
def move_with_time(self):
"""
A couple of the original pieces I found online said to
use time to change the x coordinate.
That'll be this one, with just a white circle.
It'll be set up to not alter where y draws the circle
except for the sin wave
I got some really fun results tinkering with this
"""
# variables set up to show the cool weaving effect
amplitude = 100
frequency = 4
time = (pg.time.get_ticks()//1000)
time = time % 4
if time == 0:
time += 1
# sin formula:
swf = int(-1 * math.sin(self.step * frequency) * amplitude)
# to see the weave better set time = 3, comment out to go back to time
time = 3
# set the changes
if self.x_pos < self.max_x:
self.x_pos = self.x_pos + time
self.y_pos = self.y_pos + swf
# weavy step:
self.step += 0.27
#self.step += 0.15
else:
# reset step, x_pos, move y axis up/down screen
# remove self.screen.fill(black) to let other methods from SinWave()
# draw also
black = (0, 0, 0)
self.screen.fill(black)
#weavy step:
self.step = 0.027
#self.step = 0.03
self.x_pos = 0
self.y_pos = self.start_y_pos
def draw_point(self):
""" Activate movement, draw circle accordingly """
# set a color and radius, change as desired
radius = 10
# setting the color this way allows me to change it in the movement method
# not currently in use, but future use
color = (self.red, self.green, self.blue)
white = (230, 230, 230)
# unlike original, we're only allowing one circle per method call
# fill screen to watch circle only
#black = (0, 0, 0)
#self.screen.fill(black)
pg.draw.circle(self.screen, white, (self.x_pos, self.y_pos), radius, 0)
self.move_with_time()
class PyDrawObjects(object):
"""Container for running the movement and drawing onto screen.
Remove comments to see each movement method"""
def __init__(self, screen, globals):
self.screen = screen
self.globals = globals
self.point = SinWave(self.screen, self.globals)
#self.point2 = SinWave(self.screen, self.globals)
#self.point3 = SinWave(self.screen, self.globals)
self.point4 = SinWaveTime(self.screen, self.globals)
def run_objects(self):
"""
self.point4 when it reaches edge of window, x maximum will
refill background so wave is redrawn on new surface
"""
self.point4.draw_point()
#self.point3.draw_point(third=True)
#self.point2.draw_point(second=True)
#self.point.draw_point()
def start_pygame():
""" start all pygame dependants. Return screen, timer"""
pg.init() # Not sure the proper place to put this
globals = SkullGlobals()
screen = pg.display.set_mode((globals.WIDTH, globals.HEIGHT))
pg.display.set_caption(('Pygame Display'))
animation_timer = pg.time.Clock()
pg.display.flip()
return screen, animation_timer
def pygame_loop():
"""
The loop that will run drawing and responding to events
"""
# pg.init() could go here instead of in the start_pygame()
globals = SkullGlobals()
w = globals.WIDTH
h = globals.HEIGHT
screen, timer = start_pygame()
black = (0, 0, 0)
screen.fill(black)
back_drop = PyDrawObjects(screen, globals)
running = True
test_color = (0, 255, 255)
test_location = (200, 200)
test_radius = 20
while running:
#screen.fill(globals.background_color)
# I comment the screen fill out, and do it above in the PyDrawObjects class
timer.tick(60) ## WITHOUT TIMER < MY CPU runs as fast as it can >!!!!
events = pg.event.get()
for event in events:
if event.type == pg.QUIT:
running = False
pg.QUIT
exit(0)
back_drop.run_objects()
pg.display.update()
pygame_loop()
Also, every time I thought I knew what I was doing.... pygame would show me differently. Still a work in progress, but for now, something to play with.
Update: SinWaveTime class added to produce that particular weaving effect
Tinkering with the different sin wave variables:
I wrote this piece separate from my 3D experiment to see how to manipulate the sin wave.
While trying to use time as the factor to move my pygame draw circle on the x-axis, i got this crazy little doo-dad :
I don't think it's drawing two circles at once, but if I figure out what the heck it's doing I'll let you know. Or hey if you know, drop a comment. I don't know if my comments are just not working, or no one wants to.
So, here's some pygame code to play with the sin wave. Alter the different variables to see it in action.
picture of SinWave.move_with_time()
see changes, SinWaveTime class set up to specifically produce this effect
picture of SinWave.move_point2()
picture of SinWave.move_point():
code:
There are a ton of comment in the code. It helps me remember, and my guess is they're helpful to learners like me. *or people who just go: "What the hell was she thinking!?"*
#!usr/bin/python3
# -*- coding: utf-8 -*-
import pygame as pg
import math
from sys import exit
class SkullGlobals(object):
""" class container for globally used variables """
def __init__(self):
self.WIDTH = 600
self.HEIGHT = 600
self.background_color = (130, 120, 100)
self.SAND = (130, 120, 100)
self.BLUE = (40, 60, 200)
self.LBLUE = (100, 100, 255)
self.RED = (230, 50, 50)
self.GREEN = (50, 230, 50)
self.D_WHITE = (200,200,200)
self.CENTER = (self.WIDTH//2, self.HEIGHT//2)
self.FULL_SIZE = (self.WIDTH//4 + self.HEIGHT//4)//2
self.SMALL_SIZE = (self.WIDTH//50 + self.HEIGHT//50)//2
self.base_color = 150
class SinWave(object):
def __init__(self, screen, globals):
self.screen = screen
self.globals = globals
self.x_pos = 0
self.max_x = self.globals.WIDTH
self.start_y_pos = self.globals.HEIGHT
self.y_pos = self.globals.HEIGHT
self.max_y = self.globals.HEIGHT
self.step = .015 # nice sharp 0.2 with 0.03 step
self.blue = 228
self.red = 10
self.green = 10
self.move = 11
def move_point2(self):
"""This was made to introduce a second wave with different parameters
"""
frequency = 0.3 # less frequency less wave intensity
self.x_pos += 2 # increases breadth of wave
# point position = pp
pp_y = self.y_pos
# smaller amp = more solid, small decent waves
amplitude = 10 # amp higher is taller
# sine wave formula = swf
swf = int(-1 * math.sin(self.step * frequency) * amplitude)
if self.x_pos < self.max_x:
self.x_pos += 1 # speed? Most formulas use time for the x position
# if change in step is not = original step, y position changes
self.step += 0.3
else:
# reset step, x_pos, move y axis up/down screen
self.step = 0.03
self.x_pos = 0
self.move += 1
# moving y upscreen:
self.y_pos -= self.move
if self.move > 10:
self.move = 2
if self.y_pos > -400:
self.y_pos = self.y_pos + swf
else:
# wave out of screen parameters
self.y_pos = self.start_y_pos
if self.blue <= 100:
self.blue += 15
elif self.blue > 100 and self.blue < 240:
self.blue += 10
else:
self.blue = 0
if self.green <= 100:
self.green += 15
elif self.green < 240 and self.blue > 100:
self.green += 10
else:
self.green = 0
#changes here override color changes in above else:
# they are happening on every circle draw
if self.red <= 50:
self.red += 2
if self.red <= 150:
self.red += 1
if self.red > 150 and self.red >= 50:
self.red -= 3
def move_point(self):
""" First play around with altering sin wave
color change is extremely gradual
y's position is changed in separate if/else clause.
x position is change constant. x+= 1 """
frequency = 0.3 # less frequency less wave intensity
# smaller amp = more solid, small decent waves
amplitude = 10 # amp higher is taller
# sine wave formula = swf
swf = int(-1 * math.sin(self.step * frequency) * amplitude)
if self.x_pos < self.max_x:
self.x_pos += 1
self.step += 0.15
# if change in step is not = original step, y position changes
else:
# reset step, x_pos, move y axis up/down screen
self.step = 0.03
self.x_pos = 0
self.y_pos -= self.move
if self.y_pos > -300:
self.y_pos = self.y_pos + swf
else:
self.y_pos = self.start_y_pos
if self.green < 50:
self.green += 10
elif self.green < 150:
self.green += 15
elif self.green < 240:
self.green += 5
else:
self.green = 0
if self.blue <= 50:
self.blue += 175
if self.blue >= 150:
self.blue -= 1
if self.blue >= 225:
self.blue -= 1
def move_with_time(self):
"""
A couple of the original pieces I found online said to
use time to change the x coordinate.
That'll be this one, with just a white circle.
It'll be set up to not alter where y draws the circle
except for the sin wave
I got some really fun results tinkering with this
"""
# define a frequency and amplitude:
# if either of these ends up 0, swf will = 0
amplitude = 20
frequency = 10
##############################
# cool little weavy pattern:
#frequency = 4
#amplitude = 40
#step = 0.027
#self.y_pos = self.globals.HEIGHT//2
#####################################
# set up y position to middle of screen
self.y_pos = self.globals.HEIGHT//2
#http://pygametutorials.wikidot.com/book-time
# pygame.time is measured in 1/1000 of a second
#time = (pg.time.get_ticks())//1000
# the above gradually increases, so wave speeds up visually
# it is not a constant range
time = (pg.time.get_ticks()//1000)
# modulate:
# modulating will mean the distance between x points
# can be 0 - 3, as below
# at 0 x does not move, stalling the movement across x
# so I took that out with the little if below
time = time % 3
if time == 0:
time += 1
# sin formula:
swf = int(-1 * math.sin(self.step * frequency) * amplitude)
# set the changes
if self.x_pos < self.max_x:
self.x_pos = self.x_pos + time
self.y_pos = self.y_pos + swf
# weavy step:
#self.step += 0.27
self.step += 0.3
else:
# reset step, x_pos, move y axis up/down screen
# I'm not sure if resetting the step is necessary
# it seems step can reach to infinite without messing too much
# with the wave
# still need more research on trigonometry
black = (0, 0, 0)
self.screen.fill(black)
#weavy step:
#self.step = 0.027
self.step = 0.3
self.x_pos = 0
self.y_pos = self.start_y_pos
def draw_point(self, second=False, third=False):
""" Activate movement, draw circle accordingly """
# set a color and radius, change as desired
radius = 15
# setting the color this way allows me to change it in the movement method
color = (self.red, self.green, self.blue)
# I like to dull the colors a smidge so it doesn't scream at my eyeballs
# full white is (255, 255, 255)
white = (230, 230, 230)
# I'm sure there's a better way to do the part below
# trying to make sure with each call, it only grabs one of the methods
# Or None if they try to draw more then one with a call to it.
if second == False and third == False:
pg.draw.circle(self.screen, color, (self.x_pos, self.y_pos), radius, 0)
self.move_point()
if second == True and third == False:
radius = 10
pg.draw.circle(self.screen, color, (self.x_pos, self.y_pos), radius, 0)
self.move_point2()
if third == True and second == False:
radius = 10
# fill screen to watch circle only
#black = (0, 0, 0)
#self.screen.fill(black)
pg.draw.circle(self.screen, white, (self.x_pos, self.y_pos), radius, 0)
self.move_with_time()
####### SinWaveTime --- weaving pattern #########
####### cleared out comments, I only changed a little bit##
class SinWaveTime(object):
""" Separate SinWave container for time alterations
this one stays center screen, so the other class interferes
with translation when you try to set it to center on each call"""
def __init__(self, screen, globals):
self.screen = screen
self.globals = globals
self.x_pos = 0
self.max_x = self.globals.WIDTH
self.start_y_pos = self.globals.HEIGHT//2 # <--- changed
self.y_pos = self.globals.HEIGHT//2 #<---- changed
self.max_y = self.globals.HEIGHT
self.center = self.globals.HEIGHT // 2
self.step = 0.027 # nice sharp 0.2 with 0.03 step
self.blue = 228
self.red = 10
self.green = 10
self.move = 11
def move_with_time(self):
"""
A couple of the original pieces I found online said to
use time to change the x coordinate.
That'll be this one, with just a white circle.
It'll be set up to not alter where y draws the circle
except for the sin wave
I got some really fun results tinkering with this
"""
# variables set up to show the cool weaving effect
amplitude = 100
frequency = 4
time = (pg.time.get_ticks()//1000)
time = time % 4
if time == 0:
time += 1
# sin formula:
swf = int(-1 * math.sin(self.step * frequency) * amplitude)
# to see the weave better set time = 3, comment out to go back to time
time = 3
# set the changes
if self.x_pos < self.max_x:
self.x_pos = self.x_pos + time
self.y_pos = self.y_pos + swf
# weavy step:
self.step += 0.27
#self.step += 0.15
else:
# reset step, x_pos, move y axis up/down screen
# remove self.screen.fill(black) to let other methods from SinWave()
# draw also
black = (0, 0, 0)
self.screen.fill(black)
#weavy step:
self.step = 0.027
#self.step = 0.03
self.x_pos = 0
self.y_pos = self.start_y_pos
def draw_point(self):
""" Activate movement, draw circle accordingly """
# set a color and radius, change as desired
radius = 10
# setting the color this way allows me to change it in the movement method
# not currently in use, but future use
color = (self.red, self.green, self.blue)
white = (230, 230, 230)
# unlike original, we're only allowing one circle per method call
# fill screen to watch circle only
#black = (0, 0, 0)
#self.screen.fill(black)
pg.draw.circle(self.screen, white, (self.x_pos, self.y_pos), radius, 0)
self.move_with_time()
class PyDrawObjects(object):
"""Container for running the movement and drawing onto screen.
Remove comments to see each movement method"""
def __init__(self, screen, globals):
self.screen = screen
self.globals = globals
self.point = SinWave(self.screen, self.globals)
#self.point2 = SinWave(self.screen, self.globals)
#self.point3 = SinWave(self.screen, self.globals)
self.point4 = SinWaveTime(self.screen, self.globals)
def run_objects(self):
"""
self.point4 when it reaches edge of window, x maximum will
refill background so wave is redrawn on new surface
"""
self.point4.draw_point()
#self.point3.draw_point(third=True)
#self.point2.draw_point(second=True)
#self.point.draw_point()
def start_pygame():
""" start all pygame dependants. Return screen, timer"""
pg.init() # Not sure the proper place to put this
globals = SkullGlobals()
screen = pg.display.set_mode((globals.WIDTH, globals.HEIGHT))
pg.display.set_caption(('Pygame Display'))
animation_timer = pg.time.Clock()
pg.display.flip()
return screen, animation_timer
def pygame_loop():
"""
The loop that will run drawing and responding to events
"""
# pg.init() could go here instead of in the start_pygame()
globals = SkullGlobals()
w = globals.WIDTH
h = globals.HEIGHT
screen, timer = start_pygame()
black = (0, 0, 0)
screen.fill(black)
back_drop = PyDrawObjects(screen, globals)
running = True
test_color = (0, 255, 255)
test_location = (200, 200)
test_radius = 20
while running:
#screen.fill(globals.background_color)
# I comment the screen fill out, and do it above in the PyDrawObjects class
timer.tick(60) ## WITHOUT TIMER < MY CPU runs as fast as it can >!!!!
events = pg.event.get()
for event in events:
if event.type == pg.QUIT:
running = False
pg.QUIT
exit(0)
back_drop.run_objects()
pg.display.update()
pygame_loop()
Comments
Post a Comment