Drawing a parabola with Pygame - python

I want to draw a parabola in pygame. I have made a pixelarray object and loop through it to determine if a pixel is on the parabola or not. I seem to get an image that has gaps between the points. How do I make it a single continuous line?
import pygame
import sys
from pygame.locals import *
import math
WIDTH = 640
HEIGHT = 480
pygame.init()
screen = pygame.display.set_mode((WIDTH, HEIGHT), 0, 32)
pxarray = pygame.PixelArray(screen)
while True:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
screen.fill((0,0,0))
for y, py in enumerate(pxarray):
for x, px in enumerate(py):
if int(x) == (int(y)*int(y)) - 30*int(y) + 450:
pxarray[y][x] = 0xFFFFFF
pygame.display.update()

color = 255, 0, 0
first = True
prev_x, prev_y = 0, 0
while True:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
screen.fill((0,0,0))
for y, py in enumerate(pxarray):
for x, px in enumerate(py):
if int(x) == (int(y)*int(y)) - 30*int(y) + 450:
pxarray[y][x] = 0xFFFFFF
if first:
first = False
prev_x, prev_y = x, y
continue
pygame.draw.line(screen, color, (prev_y, prev_x), (y, x))
prev_x, prev_y = x, y
first = True
pygame.display.flip()

You'll need to draw the parabola as a series of line segments. How many segments you use will determine how smooth it will look, so if you're computing the parabola x = y^2 + 30y + 450, you'd compute the x values for a number of y values and draw lines from (x0,y0) to (x1,y1) and so on.
If you don't have a line drawing primitive, you'll need to implement one using something like Bresenham's Algorithm.

Related

Pygame walk towards rotation

i'm trying to make a circle go towards the way its looking, when i put 0 it goes towards 0 but when i put 90 for some reason it goes towards like 200 or something
import pygame
import math
import random
from random import randint
pygame.init()
screen = pygame.display.set_mode([500, 500])
""""""
def rad_to_offset(radians, offset):
x = math.cos(radians) * offset
y = math.sin(radians) * offset
return [x, y]
X = 250
Y = 250
""""""
clock = pygame.time.Clock()
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
""" if i put 90 it doesnt go towards 90 """
xy = rad_to_offset(90, 1)
X += xy[0]
Y += xy[1]
print(X, Y)
screen.fill((255, 255, 255))
pygame.draw.circle(screen, (0, 0, 255), (X, Y), 20)
pygame.display.flip()
pygame.quit()
The unit of the angle in the trigonometric functions is Radian but not Degree. Use math.radians to convert from degrees to radians:
def rad_to_offset(degrees, offset):
x = math.cos(math.radians(degrees)) * offset
y = math.sin(math.radians(degrees)) * offset
return [x, y]

Pygame: Is there a way of scrolling the 'coordinate system' of a white-filled display without setting a background image?

I have a game display on which I used the blit-function to display a flight path as well as a drone. The flight path starts from the right side and goes beyond the left side of the display.
The game display is filled white and what I want is to move my drone via pressed keys from right to left along the flight path (which is just a set of contiguous lines connecting random points).
I want the 'coordinate system' of my display to move/scroll so that you can see where the flight path ends. At the same time I want my drone to maintain a static position during that scrolling, e.g. stay in the middle of the screen while it follows the flight path.
Does anybody know a function that allows me to achieve that? All I found in forums and on YouTube seemed rather complex and required one to have set a background image first. I just want the white-filled screen to scroll while I move my drone to the left to follow the red flight path. Below is what I coded so far.
Thank you a lot in advance for any advice!
import pygame
import pygame.gfxdraw
import random
import sys
white = (255,255,255)
display_width = 1200
display_height = 700
game_screen = pygame.display.set_mode((display_width,display_height))
pygame.display.set_caption('gameScreen')
the_drone = pygame.image.load('drone.png')
X=1000
Y=350
p1=[X, Y]
p2=[X, Y]
p3=[X, Y]
p4=[X, Y]
p5=[X, Y]
pointlist = [p1, p2, p3, p4, p5]
limit1=1000
limit2=850
for i in pointlist:
i[0] = random.randrange(limit2, limit1)
limit1-=300
limit2-=300
for i in pointlist:
if i == 0:
i[1] = random.randrange(200, 600)
else:
range = i[1]-1
i[1] = random.randrange(range-100, range+100)
def flightpath(pointlist):
pygame.draw.lines(game_screen, (255, 0, 0), False, pointlist, 3)
def drone(x,y):
game_screen.blit(the_drone,(X,Y))
def game_loop():
global X, Y
gameExit = False
while not gameExit:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
pygame.quit()
sys.exit()
keys = pygame.key.get_pressed() #checking pressed keys
if keys[pygame.K_LEFT]:
X -= 0.5
if keys[pygame.K_DOWN]:
Y -= 0.5
if keys[pygame.K_UP]:
Y +=0.5
game_screen.fill(white)
flightpath(pointlist)
drone(X,Y)
pygame.display.update()
game_loop()
pygame.quit()
sys.exit()
Hi to be hones I don't really understand your Code but I got it working like that:
import pygame
import sys
import random
# init window
def init():
pygame.init()
pygame.display.set_caption("Drone Game")
screen = pygame.display.set_mode((500, 500))
return screen
# make closing the window possible
def escape():
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
# draws all objects on screen
def draw(screen, f, y_pos):
screen.fill((50, 50, 50))
for y in range(20):
for x in range(5):
pygame.draw.rect(screen, f[y][x], (x * 100, (y * 100) - y_pos, 100, 100))
pygame.draw.rect(screen, (250, 0, 0), (240, 240, 20, 20)) # drone
pygame.display.update()
# creates background
def field():
f = []
for y in range(20):
f.append([])
for x in range(5):
f[y].append((random.randint(200, 255), random.randint(200, 255), random.randint(200, 255)))
return f
# combines all functions
def main(screen):
f = field()
y_pos = 500
while True:
pygame.time.Clock().tick(30)
escape()
y_pos -= 1
draw(screen, f, y_pos)
# starts program
if __name__ == '__main__':
main(init())
I hope it works for you. :)

Other ways to create line animation

I'm trying to create a animation that runs around a shape. The method I came up with is similar to the snake game, drawing the desired part and refresh it with white screen.
For example, if I want to draw a linear line animation, with the max animated length of 3:
lst = [1, 2, 3]
dummy_lst = [1, 1, 1, 2, 3, 3, 3]
colored_position = [[1,1,1], [1,1,2], [1,2,3], [2,3,3], [3,3,3]] # if the numbers overlapped, it draws the same place which is fine
and then I iterate the colored_position to get the animation done.
The real code:
import pygame
import sys
SCREEN_WIDTH = 800
CELLSIZE = 10
x, y = 150, 200
position = [[x+CELLSIZE*i, y] for i in range(50)] +\
[[x+CELLSIZE*50, y+CELLSIZE*i] for i in range(50)] +\
[[x+CELLSIZE*50-CELLSIZE*i, y+CELLSIZE*50]for i in range(50)] +\
[[x, y+CELLSIZE*50-CELLSIZE*i]for i in range(50)]
# creates fake firsts and lasts
def dummy_list(list, length):
return [list[0]]*(length-1) + list + [list[-1]]*(length-1)
def main():
pygame.init()
clock = pygame.time.Clock()
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_WIDTH))
count = 0
while True:
clock.tick(10)
screen.fill((255, 255, 255))
dummy = dummy_list(position, 50)
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
count = 0
while count < 1: # I could chaget this to see many times it rotates
for i in range(len(dummy)-50+1):
for j in range(9): # change this to adjust how wide the colored part is
pygame.draw.rect(screen, (255, 0, 0), pygame.Rect(
dummy[i+j][0], dummy[i+j][1], CELLSIZE, CELLSIZE), 0)
pygame.display.update()
screen.fill((255, 255, 255))
count += 1
pygame.display.update()
But it seems very hard-coding. since I have to know each part of the desired position's Xs and Ys. What's the smarter way to complete the task?
You want to move the object along a path. I don't see any problem in defining the path through a list of points.
However you can write a function that generates the list of points from a pygame.Rect object:
def generate_positions(rect, step):
return [[x, rect.top] for x in range(rect.left, rect.right, step)] +\
[[rect.right, y] for y in range(rect.top, rect.bottom, step)] +\
[[x, rect.bottom] for x in range(rect.right, rect.left, -step)] +\
[[rect.left, y] for y in range(rect.bottom, rect.top, -step)]
CELLSIZE = 10
x, y = 150, 200
position = generate_positions(pygame.Rect(x, y, 50*CELLSIZE, 50*CELLSIZE), CELLSIZE)
I recommend to use the application loop to draw the snake:
import pygame
import sys
SCREEN_WIDTH = 800
def generate_positions(rect, step):
return [[x, rect.top] for x in range(rect.left, rect.right, step)] +\
[[rect.right, y] for y in range(rect.top, rect.bottom, step)] +\
[[x, rect.bottom] for x in range(rect.right, rect.left, -step)] +\
[[rect.left, y] for y in range(rect.bottom, rect.top, -step)]
CELLSIZE = 10
x, y = 150, 200
position = generate_positions(pygame.Rect(x, y, 10*CELLSIZE, 10*CELLSIZE), CELLSIZE)
def main():
pygame.init()
clock = pygame.time.Clock()
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_WIDTH))
current_point = None
snake_len = 9
while True:
clock.tick(10)
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
current_point = -snake_len
screen.fill((255, 255, 255))
if current_point != None:
for i in range(max(0, current_point), min(len(position), current_point+snake_len)):
pygame.draw.rect(screen, (255, 0, 0), pygame.Rect(*position[i], CELLSIZE, CELLSIZE), 0)
current_point += 1
if current_point >= len(position):
current_point = None
pygame.display.update()
main()

How to code a rectangles that start from right in circular motion in pygame

The problem is that I want to draw small square/rect in a circle from left to right. Somewhat like this:
In pygame, the rectangles number should be 120.
But whenever use this function:
x = int(math.cos(angle) * 50) + origin X
y = int(math.sin(angle) * 50) + origin Y
It starts from two different points, and if I adjust the angle it starts at five different points.
I want it to start from right in full circle.
import pygame, sys, math
run = True
white = (255, 255, 255)
black = (0, 0, 0)
angle = 0
size = widht, height = 800, 600
pygame.init()
screen = pygame.display.set_mode(size)
clock = pygame.time.Clock()
run = True
while run:
msElapsed = clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
screen.fill(white)
i = 1
while i < 28:
x = int(math.cos(angle) * 100) + 300
y = int(math.sin(angle) * 100) + 200
pygame.draw.rect(screen, black, (x, y, 10, 10))
i += 1
angle += 5
print(x)
print(y)
pygame.display.flip()
pygame.quite()
and output are
The unit of the angle for Trigonometric functions (e.g. math.cos, math.sin) in the math module is Radian rather than degree. math.pi*2 Radian is 360 Degrees.
If you want to distribute 28 rectangles uniformly around a circle, then the angle from 1 rectangle to the next is math.pi*2 / 28. e.g.:
run = True
while run:
msElapsed = clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
screen.fill(white)
for i in range(28):
angle = i / 28 * math.pi * 2 # 2*pi radian == 360°
x = int(math.cos(angle) * 100) + 400
y = int(math.sin(angle) * 100) + 300
pygame.draw.rect(screen, black, (x-5, y-5, 10, 10))
pygame.display.flip()

pygame draw function

Apologies in advance if this is a simple fix but I couldn't find anything on it. I am relatively new to pygame but I can't understand why when I run this the first bar that is drawn is always half cut off. To me anyway I should start a 0,400 and draw from 0 across 40 and then up. If this is not the case please enlighten a curious mind
from pygame import *
import pygame, sys, random
pygame.init()
screen = pygame.display.set_mode((1000,400))
colour = (0, 255, 0)
array = []
x, y, z, b = -80, 0, 0, 0
flag = True
for c in range(5):
array.append(random.randint(100, 400));
for c in array:
print c
while True:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
if len(array) == z:
flag = False
if flag == True:
b = array[z]
x += 80
z += 1
pygame.draw.line(screen, colour, (x, 400), (x, (400-b)), 40)
pygame.display.update()
pygame is drawing a line from (0,400) to (0, 400-b), with line thickness 40.
Here is an way to shift the lines so each is fully visible:
for i, b in enumerate(array):
x = i*80 + 20 # <-- add 20 to shift by half the linewidth
pygame.draw.line(screen, colour, (x, 400), (x, (400-b)), 40)
import sys
import random
import pygame
pygame.init()
screen = pygame.display.set_mode((1000,400))
colour = (0, 255, 0)
array = [random.randint(100, 400) for c in range(5)]
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
linewidth = 40
for i, b in enumerate(array):
x = i*linewidth*2 + linewidth//2
pygame.draw.line(screen, colour, (x, 400), (x, (400-b)), linewidth)
pygame.display.update()

Categories