Adding Anti-Aliasing & Filling the Circle with color in Mid-Point Circle Drawing Algorithm - graphics

Cannot figure out how to add anti-aliasing & color the circle produced from Mid-Point Circle Drawing Algorithm. The following is my code, should I implement it using another library?
from pygame import gfxdraw
import sys,pygame
pygame.init()
screen = pygame.display.set_mode((400,400))
screen.fill((0,0,0))
pygame.display.flip()
def circle(radius,offset):
x,y = 0,radius
plotCircle(x,y,radius,offset)
def symmetry_points(x,y,offset):
gfxdraw.pixel(screen,x+offset,y+offset,(255,255,255))
gfxdraw.pixel(screen,-x+offset,y+offset,(255,255,255))
gfxdraw.pixel(screen,x+offset,-y+offset,(255,255,255))
gfxdraw.pixel(screen,-x+offset,-y+offset,(255,255,255))
gfxdraw.pixel(screen,y+offset,x+offset,(255,255,255))
gfxdraw.pixel(screen,-y+offset,x+offset,(255,255,255))
gfxdraw.pixel(screen,y+offset,-x+offset,(255,255,255))
gfxdraw.pixel(screen,-y+offset,-x+offset,(255,255,255))
pygame.display.flip()
def plotCircle(x,y,radius,offset):
d = 5/4.0 - radius
symmetry_points(x,y,radius+offset)
while x < y:
if d < 0:
x += 1
d += 2*x + 1
else:
x += 1
y -= 1
d += 2*(x-y) + 1
symmetry_points(x,y,radius+offset)
circle(100,25) # circle(radius,<offset from edge>)
pygame.display.flip()
while 1:
for event in pygame.event.get():
if event.type == pygame.QUIT: sys.exit()

Related

Why it doesn't spin in a circle? And how to fix it?

I'm not sure what the name of the shape that is being created, but I think is a combination of circle and square or maybe is similar to a cylinder. You can run the code to see what shape it makes. And could you suggest a site where I can learn to code a game (algorithms behind the basic games)? I hope you understand what I mean because I'm not good at English.
import pygame
import sys
import math
pygame.init()
width = 640
height = 480
screen = pygame.display.set_mode((width,height))
img = pygame.Surface((50,50))
img.set_colorkey((255,0,0))
angle = 0
clock = pygame.time.Clock()
c_list = []
x = 100
y = 100
vel = 5
def draw_line(surface, color, pos1, pos2):
pygame.draw.line(surface, color, pos1, pos2)
while True:
screen.fill((122,122,122))
keys = pygame.key.get_pressed()
angle -= 3
if angle % 360 < 90:
x -= math.sin(angle/180*math.pi)**2*vel
y -= math.cos(angle/180*math.pi)**2*vel
elif angle % 360 < 180:
x -= math.sin(angle/180*math.pi)**2*vel
y += math.cos(angle/180*math.pi)**2*vel
elif angle % 360 < 270:
x += math.sin(angle/180*math.pi)**2*vel
y += math.cos(angle/180*math.pi)**2*vel
else:
x += math.sin(angle/180*math.pi)**2*vel
y -= math.cos(angle/180*math.pi)**2*vel
if (x,y) not in c_list:
c_list.append((x,y))
for i in range(len(c_list)-1):
draw_line(screen,(0,0,0),c_list[i],c_list[i+1])
clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit(-1)
img_copy = pygame.transform.rotate(img, angle)
screen.blit(img_copy,(x-int(img_copy.get_width()/2),y-int(img_copy.get_width()/2)))
pygame.display.flip()
You have to find the tangent of the circle. If you have an angle then the vector to the point on the circle is:
vx, vy = cos(angle), sin(angle)
The tangent to the circle is the vector rotated by 90°:
tx, ty = -vy, vy
Add the tangent multiplied by the velocity to the point (x, y) in every frame:
x -= math.sin(angle*math.pi/180)*vel
y += math.cos(angle*math.pi/180)*vel
angle += 3
See also Move and rotate.
Minimal example:
import pygame
import sys
import math
pygame.init()
width = 640
height = 480
screen = pygame.display.set_mode((width,height))
clock = pygame.time.Clock()
img = pygame.Surface((50,50))
img.set_colorkey((255,0,0))
angle = 0
c_list = []
x, y = 300, 200
vel = 5
def draw_line(surface, color, pos1, pos2):
pygame.draw.line(surface, color, pos1, pos2)
start = False
while True:
screen.fill((122,122,122))
keys = pygame.key.get_pressed()
x -= math.sin(angle*math.pi/180)*vel
y += math.cos(angle*math.pi/180)*vel
angle += 3
if (x,y) not in c_list:
c_list.append((x,y))
for i in range(len(c_list)-1):
draw_line(screen,(0,0,0),c_list[i],c_list[i+1])
clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit(-1)
img_copy = pygame.transform.rotate(img, -angle)
screen.blit(img_copy,(x-int(img_copy.get_width()/2),y-int(img_copy.get_width()/2)))
pygame.display.flip()

How to make a ball slow down, and "bounce", then slow down even more? [duplicate]

The code below bounces a ball but for some reason the ball goes through the ground after it finishes its bounces. Anyone Know Why? The idea of the code is a ball starts at the top left corner and then falls and bounces and then goes up and back down and so on until it stops bouncing, but when it stops bouncing it starts jittering and slowly sinks through the ground. Idk why and I cant figure it out. Anyone know why? Thanks for the help
import pygame
pygame.init()
#All keyboard and mouse input will be handled by the following function
def handleEvents():
#This next line of code lets this function access the dx and dy
#variables without passing them to the function or returning them.
global dx,dy
#Check for new events
for event in pygame.event.get():
#This if makes it so that clicking the X actually closes the game
#weird that that wouldn't be default.
if event.type == pygame.QUIT:
pygame.quit(); exit()
#Has any key been pressed?
elif event.type == pygame.KEYDOWN:
#Escape key also closes the game.
if event.key == pygame.K_ESCAPE:
pygame.quit(); exit()
elif event.key == pygame.K_RIGHT or event.key == pygame.K_d:
dx = dx + 5
elif event.key == pygame.K_LEFT or event.key == pygame.K_a:
dx = dx - 5
elif event.key == pygame.K_UP or event.key == pygame.K_w:
dy = dy - 5
elif event.key == pygame.K_DOWN or event.key == pygame.K_s:
dy = dy + 5
width = 1000
height = 600
size = (width, height)
black = (0, 0, 0) #r g b
screen = pygame.display.set_mode(size)
clock = pygame.time.Clock()
ball = pygame.image.load("ball.gif")
ballrect = ball.get_rect()
x = 0
y = 0
dx = 3
dy = 3
done = False
while not done:
handleEvents()
#Move the ball
x = x + dx
y = y + dy
ballrect.topleft = (x,y)
#PART A
if ballrect.left < 0 or ballrect.right > width:
dx = -dx
if ballrect.top < 0 or ballrect.bottom > height:
dy = -dy
'''If the ball is outside of the range delta y,
then delta y becomes the negative version of it, and the same goes
for delta x if it is outside the boundries of delta x
'''
#PART B
dy = dy * 0.99
dx = dx * 0.99
'''Could be useful if you want
the ball to stop moving after a certain amount of time,
or the opposite, it could make the ball slowly move a greater distance each frame'''
#PART C
dy = dy + 0.3
'''dy slowly gets .3 added to itself each frame, making the bounce
smaller each time until eventually it stops fully'''
#Draw everything
screen.fill(black)
screen.blit(ball, ballrect)
pygame.display.flip()
#Delay to get 30 fps
clock.tick(30)
pygame.quit()
Since the falling speed of the ball is greater than 1 pixel, you have to make sure that the ball does not fall below the lower edge of the window.
You need to constrain the bottom of the ball to the bottom of the window:
done = False
while not done:
# [...]
x = x + dx
y = y + dy
ballrect.topleft = (x,y)
#PART A
if ballrect.left < 0 or ballrect.right > width:
dx = -dx
if ballrect.top < 0:
dy = -dy
if ballrect.bottom > height:
ballrect.bottom = height # <---
y = ballrect.top # <---
dy = -dy
# [...]

Mouse click detection in pygame

I have a task, where I have a square 3X3 and for every click in the small square, this square will paint in red. Here is my code yet. I think I did something wrong in my first while loop, but I'm not sure. Please help me.
import pygame
pygame.init()
#create a screen
screen = pygame.display.set_mode((400, 400))
#colors
white = [255, 255, 255]
red = [255, 0, 0]
x = 0
y = 0
#create my square
for j in range(3):
for i in range(3):
pygame.draw.rect(screen, white, (x, y, 30, 30), 1)
x += 30
if x == 90:
x = 0
y += 30
pygame.display.flip()
running = 1
while running:
event = pygame.event.poll()
#found in what position my mouse is
if event.type == pygame.QUIT:
running = 0
elif event.type == pygame.MOUSEMOTION:
print("mouse at (%d, %d)" % event.pos)
mouse = pygame.mouse.get_pos()
click = pygame.mouse.get_pressed()
#mouse click
if click[0] == 1 and x in range(30) and y in range (30):
pygame.draw.rect(screen, red, (30, 30 , 29 ,29))
while pygame.event.wait().type != pygame.QUIT:
pygame.display.change()
You have to update your screen each time when you draw or do something in screen. So, put this line under your first while loop.
pygame.display.flip()
In your condition you was checking x and y and which are not mouse position.
if click[0] == 1 and x in range(30) and y in range (30):
Check your mouse position in range(90) because of you have three rectangular and the are 30x30.
if click[0] == 1 and mouse[0] in range(90) and mouse[1] in range (90):
Then, set your rectangular start position to fill the mouse point.
rect_x = 30*(mouse[0]//30) # set start x position of rectangular
rect_y = 30*(mouse[1]//30) # set start y position of rectangular
You can edit your code with this.
while running:
pygame.display.flip()
event = pygame.event.poll()
#found in what position my mouse is
if event.type == pygame.QUIT:
running = 0
elif event.type == pygame.MOUSEMOTION:
print("mouse at (%d, %d)" % event.pos)
mouse = pygame.mouse.get_pos()
click = pygame.mouse.get_pressed()
#mouse click
if click[0] == 1 and mouse[0] in range(90) and mouse[1] in range (90):
'''
rect_x = 30*(0//30) = 0
rect_y = 30*(70//30) = 60
'''
rect_x = 30*(mouse[0]//30) # set start x position of rectangular
rect_y = 30*(mouse[1]//30) # set start y position of rectangular
pygame.draw.rect(screen, red, (rect_x, rect_y , 30 , 30)) # rectangular (height, width), (30, 30)

Collision between two circle in pygame [duplicate]

This question already has answers here:
Pygame how to let balls collide
(2 answers)
pygame Get the balls to bounce off each other
(1 answer)
Closed 2 years ago.
I am trying to create my first game, where I have successfully added a bouncing ball and another ball around the mouse-pointer. The collision between these two circles works fine except sometimes the circles intersects each other hugely and the collision does not occur in a single frame, and some strange behaviour thereafter. How do I fix this?
import pygame
from pygame.locals import *
import numpy as np
# Define the colors we will use in RGB format
BLACK = ( 0, 0, 0)
WHITE = (255, 255, 255)
BLUE = ( 0, 0, 255)
GREEN = ( 0, 255, 0)
RED = (255, 0, 0)
width = 800
height = 600
radius = 40
mRadius = 60
base = 20
g = 0.2
pygame.init()
screen = pygame.display.set_mode((width,height))
pygame.display.set_caption('Testing')
clock = pygame.time.Clock()
class Circle:
def __init__(self):
self.pos = np.array([100,100])
self.velocity = np.array([2,0])
def upgrade(self,mouse):
self.pos = np.add(self.velocity,self.pos)
if ((self.pos[0] > width - radius - 1) or (self.pos[0] < 0 + radius)):
self.velocity[0] *= -1
if self.pos[1] > height - radius - base - 1:
self.velocity[1] *= -1
#print(str(self.velocity[1])+"\t"+str(self.pos[1]))
else:
self.velocity = np.add(self.velocity,[0,g])
if ((radius + mRadius)**2 >= ((self.pos[0] - mouse[0])**2 +(self.pos[1] - mouse[1])**2)):
self.pos = np.subtract(self.pos,self.velocity)
lx = self.pos[0] - mouse[0]
ly = self.pos[1] - mouse[1]
A = (lx**2 - ly**2)/(lx**2 + ly**2)
B = 2*lx*ly/(lx**2 + ly**2)
M = np.array([[A,B],[B,(-1)*A]])
self.velocity = list((-1)*M.dot(self.velocity))
print(str(lx)+"\t"+str(ly)+"\t"+str(mouse))
pygame.draw.circle(screen, GREEN, [int(self.pos[0]),int(self.pos[1])], radius)
return True
def main():
mouse = [100,100]
running = True
ball = Circle()
while running:
(mouse[0],mouse[1]) = pygame.mouse.get_pos()
screen.fill(WHITE)
pygame.draw.circle(screen, BLUE, mouse, mRadius)
running = ball.upgrade(mouse)
pygame.draw.rect(screen,RED,(0,height-base,width,base))
pygame.display.update()
clock.tick(120)
for event in pygame.event.get():
if event.type == QUIT:
running = False
if event.type == KEYDOWN and event.key == K_ESCAPE:
running = False
pygame.display.quit()
if __name__ == '__main__':
main()
Here is the github link

How to generate the food for a snake game

I can not figure out how to generate the food for the snake to eat. I know the position of the snake at line 97 and 98, I have created a class to generate a pixel where I want to draw a peace of food at line 22 (EDIT: should probably be a function, commented #def (?) in the code). All I have to do is add 15 pixels at the x and y coordinates from the position that is randomly allocated and print it to get a block.
The problem is to check if I eat it or not. It should be something like:
if x >= x_food && x <= x_food + 15 || y >= y_food && y <= y_food + 15:
...add a point and make snake longer...
The problem is putting it all together for some reason.. Can some one give me a hint or solve how I should write this class so I can continue with other problems? Thank you!
import pygame
import random
#Global variables
#Color
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
#Start length of snake
snake_length = 3
#Set the width of the segments of the snake
segment_width = 15
segment_height = 15
# Margin within each segment
segment_margin = 3
#Set initial speed
x_change = segment_width + segment_margin
y_change = 0
#def (?)
class Food():
#Class to print food
x_food = random.randint(0, 785)
y_food = random.randint(0, 585)
class Segment(pygame.sprite.Sprite):
""" Class to represent the segment of the snake. """
# Methods
# Constructer function
def __init__(self, x, y):
#Call the parents constructor
super().__init__()
#Set height, width
self.image = pygame.Surface([segment_width, segment_height])
self.image.fill(WHITE)
#Make our top-left corner the passed-in location.
self.rect = self.image.get_rect()
self.rect.x = x
self.rect.y = y
#Call this function so the Pygame library can initialize itself
pygame.init()
#Create an 800x600 size screen
screen = pygame.display.set_mode([800, 600])
#Set the title of the window
pygame.display.set_caption("Snake")
allspriteslist = pygame.sprite.Group()
#Create an initial snake
snake_segments = []
for i in range(snake_length):
x = 250 - (segment_width + segment_margin) * i
y = 30
segment = Segment(x, y)
snake_segments.append(segment)
allspriteslist.add(segment)
clock = pygame.time.Clock()
done = False
while not done:
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
#Set the speed based on the key pressed
#We want the speed to be enough that we move a full
#Segment, plus the margin
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
x_change = (segment_width + segment_margin) * -1
y_change = 0
if event.key == pygame.K_RIGHT:
x_change = (segment_width + segment_margin)
y_change = 0
if event.key == pygame.K_UP:
x_change = 0
y_change = (segment_height + segment_margin) * -1
if event.key == pygame.K_DOWN:
x_change = 0
y_change = (segment_width + segment_margin)
#Get rid of last segment of the snake
#.pop() command removes last item in list
old_segment = snake_segments.pop()
allspriteslist.remove(old_segment)
#Figure out where new segment will be
x = snake_segments[0].rect.x + x_change
y = snake_segments[0].rect.y + y_change
segment = Segment(x, y)
#Insert new segment to the list
snake_segments.insert(0, segment)
allspriteslist.add(segment)
#Draw
#Clear screen
screen.fill(BLACK)
allspriteslist.draw(screen)
#Flip screen
pygame.display.flip()
#Pause
clock.tick(5)
pygame.quit()
i took your code and i think i work something out, pls note that this only monitors when the snake goes over the block, then it prints: yummy, so you will have to add the detail, also note that i dont use your class to generate the food:
import pygame
import random
#Global variables
#Color
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
#Start length of snake
snake_length = 3
#Set the width of the segments of the snake
segment_width = 15
segment_height = 15
# Margin within each segment
segment_margin = 3
#Set initial speed
x_change = segment_width + segment_margin
y_change = 0
#def (?)
class Food():
#Class to print food
x_food = random.randint(0, 785)
y_food = random.randint(0, 585)
class Segment(pygame.sprite.Sprite):
""" Class to represent the segment of the snake. """
# Methods
# Constructer function
def __init__(self, x, y):
#Call the parents constructor
super().__init__()
#Set height, width
self.image = pygame.Surface([segment_width, segment_height])
self.image.fill(WHITE)
#Make our top-left corner the passed-in location.
self.rect = self.image.get_rect()
self.rect.x = x
self.rect.y = y
#Call this function so the Pygame library can initialize itself
pygame.init()
#Create an 800x600 size screen
screen = pygame.display.set_mode([800, 600])
#Set the title of the window
pygame.display.set_caption("Snake")
allspriteslist = pygame.sprite.Group()
#Create an initial snake
snake_segments = []
for i in range(snake_length):
x = 250 - (segment_width + segment_margin) * i
y = 30
segment = Segment(x, y)
snake_segments.append(segment)
allspriteslist.add(segment)
clock = pygame.time.Clock()
done = False
x_food = random.randint(0, 785)
y_food = random.randint(0, 585)
while not done:
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
#Set the speed based on the key pressed
#We want the speed to be enough that we move a full
#Segment, plus the margin
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
x_change = (segment_width + segment_margin) * -1
y_change = 0
if event.key == pygame.K_RIGHT:
x_change = (segment_width + segment_margin)
y_change = 0
if event.key == pygame.K_UP:
x_change = 0
y_change = (segment_height + segment_margin) * -1
if event.key == pygame.K_DOWN:
x_change = 0
y_change = (segment_width + segment_margin)
if y < y_food+30:
if x > x_food and x < x_food+30 or x+20 > x_food and x+20<x_food+30:
print('yummy')
#Get rid of last segment of the snake
#.pop() command removes last item in list
old_segment = snake_segments.pop()
allspriteslist.remove(old_segment)
#Figure out where new segment will be
x = snake_segments[0].rect.x + x_change
y = snake_segments[0].rect.y + y_change
segment = Segment(x, y)
#Insert new segment to the list
snake_segments.insert(0, segment)
allspriteslist.add(segment)
#Draw
#Clear screen
screen.fill(BLACK)
pygame.draw.rect(screen, WHITE, [x_food, y_food, 30, 30])
allspriteslist.draw(screen)
#Flip screen
pygame.display.flip()
#Pause
clock.tick(5)
pygame.quit()
hope this helped, thanks!
if x >= x_food && x <= x_food + 15 || y >= y_food && y <= y_food + 15:
Why do you OR these pairs of conditions? Don't all 4 tests have to be true at the same time?
if x >= x_food && x <= x_food + 15 && y >= y_food && y <= y_food + 15:
how about using:
if snake_headx == foodx and snake_heady == foody:
food_eated()
snake_grow()
just a suggestion though
didnt read all ur code, just thought u might find it usefull.
actuely ive came to a solution, so basicly what you want is a square, and when the snake comes near that square something should happen?, well ive got a racegame that makes you crash when you hit a square car, so il just copy the code here:
if y < thing_starty+thing_height:
if x > thing_startx and x < thing_startx+thing_width or x+car_width > thing_startx and x+car_width<thing_startx+thing_width:
snake_eated()
snake_grow()
this monitors the x and y of your car (or snake) and checks when the thing (or food) 's y is smaller than your car, then it checks the x's and alot of other things, and basicly it creates a big line all around your square that you cannot cross in your case you'd just need to add the rest, would this work?
Make your food a sprite with a simple filled rectangle as the image, and then use sprite collision pygame.sprite.spritecollide() to check if your snake collides with your food. Pygame will take care of the actual logic whether two rectangles overlap for you.
Also, since you are already using sprite groups, I suggest you write an update function for your snake segments which moves them instead of creating a new segment every turn. Then you can simply call allspriteslist.update() in your main game loop, which will call the update function for every snake segment.
Finally, you might want to have a look at the numerous snake examples on the pygame website.

Resources