drawing lines but i don't see them on the screen - python

When i run this code, to try to draw a grid for a snake game:
import pygame
pygame.init()
pygame.display.set_caption('Snake')
class grid(object):
def __init__(self, rows, width, x, y):
self.rows = rows
self.width = width
self.x = x
self.y = y
self.sizeBetween = width // rows
def draw(self, surface):
for l in range(self.rows):
self.x += self.sizeBetween
self.y += self.sizeBetween
pygame.draw.line(win, (255, 255, 255), (self.x, 0), (self.x, self.width))
pygame.draw.line(win, (255, 255, 255), (0, self.y), (self.width, self.y))
def window(surface):
grid.draw(surface)
pygame.display.update()
grid = grid(20, 500, 0, 0)
win = pygame.display.set_mode((grid.width, grid.width))
run = True
while run:
win.fill((0, 0, 0))
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
window(win)
It doesn't draw any lines. I'm new to pygame and don't really know how to fix problems like this, since it will just open a black box without any errors.

The grid is only drawn for a short moment in the 1st frame, because the attributes x and y are incremented continuously, but never reset.
def draw(self, surface):
for l in range(self.rows):
self.x += self.sizeBetween
self.y += self.sizeBetween
In the 2nd frame, the display is cleared, but the current value of the attributes x and y is self.rows * self.sizeBetween. Hence all the lines are drawn out of the window.
Change the drawing of the grid:
class Grid(object):
# [...]
def draw(self, surface):
x, y = self.x, self.y
for l in range(self.rows-1):
x += self.sizeBetween
y += self.sizeBetween
pygame.draw.line(surface, (255, 255, 255), (x, 0), (x, self.width))
pygame.draw.line(surface, (255, 255, 255), (0, y), (self.width, y))
Side note, the name of the class grid and the instance gird are identical. This causes that the instance covers the class. Python is case sensitive and class names should normally use the CapWords convention. See Style Guide for Python Code - Class Names.
I recommend to change the name of the class:
class Grid(object):
# [...]
# [...]
grid = Grid(20, 500, 0, 0)

Related

How to draw shapes using the grouping thing

I just learned how to group stuff in pygame but when I try to use it to draw a sprite it says: " ExternalError: TypeError: Cannot read property 'left' of undefined on line 32"
Here is my code:
import pygame
from pygame import *
screen = pygame.display.set_mode((600, 600))
blocks = pygame.sprite.Group()
class Block():
def __init__(self, x, y, w, h, typ):
super().__init__()
self.x = x
self.y = y
self.w = w
self.h = h
self.typ = typ
def draw(self):
pygame.draw.rect(screen, (0, 0, 0), (self.x, self.y, self.w, self.h))
class Player():
def __init__(self, x, y):
super().__init__()
self.x = x
self.y = y
self.accX = 0
self.accY = 0
def draw(self):
pygame.draw.rect(screen, (0, 0, 0), (self.x, self.y, 20, 20))
player = Player(0, 0)
while True:
Blocks = Block(0, 0, 100, 50, 1)
blocks.add(Blocks)
blocks.draw(screen)
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
pygame.display.update()
pygame.sprite.Group.draw() and pygame.sprite.Group.update() are methods which are provided by pygame.sprite.Group.
The former delegates the to the update method of the contained pygame.sprite.Sprites - you have to implement the method. See pygame.sprite.Group.update():
Calls the update() method on all Sprites in the Group [...]
The later uses the image and rect attributes of the contained pygame.sprite.Sprites to draw the objects - you have to ensure that the pygame.sprite.Sprites have the required attributes. See pygame.sprite.Group.draw():
Draws the contained Sprites to the Surface argument. This uses the Sprite.image attribute for the source surface, and Sprite.rect. [...]
This means Block and Player must to be derived from pygame.sprite.Sprite and has to have the attributes rect and image. Add the Block and Player instances to a Group and us the darw() method to draw them.
Complete example:
import pygame
from pygame import *
screen = pygame.display.set_mode((600, 600))
class Block(pygame.sprite.Sprite):
def __init__(self, x, y, w, h, typ):
super().__init__()
self.image = pygame.Surface((w, h))
self.image.fill((127, 127, 127))
self.rect = self.image.get_rect(topleft = (x, y))
class Player(pygame.sprite.Sprite):
def __init__(self, x, y):
super().__init__()
self.image = pygame.Surface((20, 20))
self.image.fill((255, 255, 0))
self.rect = self.image.get_rect(topleft = (x, y))
blocks = pygame.sprite.Group()
objects = pygame.sprite.Group()
block = Block(0, 0, 100, 50, 1)
blocks.add(block)
player = Player(0, 0)
objects.add(player)
clock = pygame.time.Clock()
run = True
while run:
clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
screen.fill((0, 0, 0))
blocks.draw(screen)
objects.draw(screen)
pygame.display.update()
pygame.quit()

Python: How to make drawn elements snap to grid in pygame

I am experimenting with a Pathfinding project and got stuck while creating a working GUI. I'm using pygame and already created a grid and a feature, which draws cubes when you press (or keep pressing) the mouse-button. However, these cubes just go wherever you click, and do not snap to the grid. I thought about using modulo somehow but I cannot seem to get it to work. Please find the code attached below. The Cube class is what I use for the squares drawn on the screen. Moreover, the drawgrid() function is how I set up my grid. I'd love some help on this, as I've been stuck on this roadblock for three days now.
class Cube:
def update(self):
self.cx, self.cy = pygame.mouse.get_pos()
self.square = pygame.Rect(self.cx, self.cy, 20, 20)
def draw(self):
click = pygame.mouse.get_pressed()
if click[0]: # evaluate left button
pygame.draw.rect(screen, (255, 255, 255), self.square)
Other drawgrid() function:
def drawgrid(w, rows, surface):
sizebtwn = w // rows # Distance between Lines
x = 0
y = 0
for i in range(rows):
x = x + sizebtwn
y = y + sizebtwn
pygame.draw.line(surface, (255, 255, 255), (x, 0), (x, w))
pygame.draw.line(surface, (255, 255, 255), (0, y), (w, y))
You have to align the position to the grids size. Use the floor division operator (//) to divide the coordinates by the size of a cell and compute the integral index in the grid:
x, y = pygame.mouse.get_pos()
ix = x // sizebtwn
iy = y // sizebtwn
Multiply the result by the size of a cell to compute the coordinate:
self.cx, self.cy = ix * sizebtwn, iy * sizebtwn
Minimal example:
import pygame
pygame.init()
screen = pygame.display.set_mode((200, 200))
clock = pygame.time.Clock()
def drawgrid(w, rows, surface):
sizebtwn = w // rows
for i in range(0, w, sizebtwn):
x, y = i, i
pygame.draw.line(surface, (255, 255, 255), (x, 0), (x, w))
pygame.draw.line(surface, (255, 255, 255), (0, y), (w, y))
class Cube:
def update(self, sizebtwn):
x, y = pygame.mouse.get_pos()
ix = x // sizebtwn
iy = y // sizebtwn
self.cx, self.cy = ix * sizebtwn, iy * sizebtwn
self.square = pygame.Rect(self.cx, self.cy, sizebtwn, sizebtwn)
def draw(self, surface):
click = pygame.mouse.get_pressed()
if click[0]:
pygame.draw.rect(surface, (255, 255, 255), self.square)
cube = Cube()
run = True
while run:
clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
cube.update(screen.get_width() // 10)
screen.fill(0)
drawgrid(screen.get_width(), 10, screen)
cube.draw(screen)
pygame.display.flip()

Trying to use OOP for bouncing ball in pong game

So recently I got into OOP, which is a very new topic for me, and I had already made a pong game that did not employ objects and I'm thinking of doing a new script with objects utilised. The problem is, when I run the code, it displays an empty screen and I'm not sure what I did wrong (I'm still new to OOP). Can anyone help out?
import pygame
class Ball():
def __init__(self, x, y, xmove, ymove, color, size):
self.x = 0
self.y = 0
self.xmove = 0
self.ymove = 0
self.color = (255, 255, 255)
self.size = 10
def draw(self, screen):
pygame.draw.circle(screen, self.color, [self.x, self.y], self.size)
def ballmove(self):
self.x += self.xmove
self.y += self.ymove
done = False
pygame.init()
WIDTH = 640
HEIGHT = 480
clock = pygame.time.Clock()
screen = pygame.display.set_mode((WIDTH, HEIGHT))
ball = Ball(0, 0, 1.5, 1.5, [255, 255, 255], 10)
while done != False:
screen.fill(0)
ball.ballmove()
ball.draw(screen)
pygame.display.update()
I think you used a wrong condtion in your loop. It should mean while done == False: or while done != True:
Also your constructor is wrong. The parameter you give to the ball will never set, because you initialized all paramters with default values. Use this constructor instead
def __init__(self, x, y, xmove, ymove, color, size):
self.x = x
self.y = y
self.xmove = xmove
self.ymove = ymove
self.color = color
self.size = size

Pygame drawing a rectangle with OOP

I'm trying to learn OOP with pygame and make a simple game, I'm loosely following a tutorial, but have tried to modify it to fit my own needs and now it's not working. I'm trying to draw a white rectangle onto a black window, the tutorial draws a blue circle on a black window and when I replace the circle to a rectangle it doesn't work.
My code is sepereated into 2 different files heres the first file:
import pygame
import LanderHandler
black = (0, 0, 0)
white = (255, 255, 255)
green = (0, 255, 0)
red = (255, 0, 0)
class MainLoop(object):
def __init__(self, width=640, height=400):
pygame.init()
pygame.display.set_caption("Lander Game")
self.width = width
self.height = height
self.screen = pygame.display.set_mode((self.width, self.height), pygame.DOUBLEBUF)
self.background = pygame.Surface(self.screen.get_size()).convert()
def paint(self):
lander = LanderHandler.Lander()
lander.blit(self.background)
def run(self):
self.paint()
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
running = False
pygame.display.flip()
pygame.quit()
if __name__ == '__main__':
# call with width of window and fps
MainLoop().run()
And my second file:
import pygame
black = (0, 0, 0)
white = (255, 255, 255)
green = (0, 255, 0)
red = (255, 0, 0)
class Lander(object):
def __init__(self, height=10, width=10, color=white, x=320, y=240):
self.x = x
self.y = y
self.height = height
self.width = width
self.surface = pygame.Surface((2 * self.height, 2 * self.width))
self.color = color
pygame.draw.rect(self.surface, white, (self.height, self.height, self.width, self.width))
def blit(self, background):
"""blit the Ball on the background"""
background.blit(self.surface, (self.x, self.y))
def move(self, change_x, change_y):
self.change_x = change_x
self.change_y = change_y
self.x += self.change_x
self.y += self.change_y
if self.x > 300 or self.x < 0:
self.change_x = -self.change_x
if self.y > 300 or self.y < 0:
self.change_y = -self.change_y
Any help or pointing me in the right direction would be amazing thank you.
P.S. I get no running errors and a black window does pop up, but without a white rectangle.
Problem is because you draw rectangle on surface self.background
lander.blit(self.background)
but you never blit self.background on self.screen which is main buffer and which is send on monitor when you do
pygame.display.flip()
So you can draw directly on self.screen
lander.blit(self.screen)
or you have to blit self.background on self.screen
lander.blit(self.background)
self.screen.blit(self.background, (0,0))
You shouldn't create a function with the name blit because it might get in the way of the actual blit function. Also right here in the second code:
pygame.draw.rect(self.surface, white, (self.height, self.height, self.width, self.width))
you should use surface

Tile-based movement pygame [duplicate]

I am experimenting with a Pathfinding project and got stuck while creating a working GUI. I'm using pygame and already created a grid and a feature, which draws cubes when you press (or keep pressing) the mouse-button. However, these cubes just go wherever you click, and do not snap to the grid. I thought about using modulo somehow but I cannot seem to get it to work. Please find the code attached below. The Cube class is what I use for the squares drawn on the screen. Moreover, the drawgrid() function is how I set up my grid. I'd love some help on this, as I've been stuck on this roadblock for three days now.
class Cube:
def update(self):
self.cx, self.cy = pygame.mouse.get_pos()
self.square = pygame.Rect(self.cx, self.cy, 20, 20)
def draw(self):
click = pygame.mouse.get_pressed()
if click[0]: # evaluate left button
pygame.draw.rect(screen, (255, 255, 255), self.square)
Other drawgrid() function:
def drawgrid(w, rows, surface):
sizebtwn = w // rows # Distance between Lines
x = 0
y = 0
for i in range(rows):
x = x + sizebtwn
y = y + sizebtwn
pygame.draw.line(surface, (255, 255, 255), (x, 0), (x, w))
pygame.draw.line(surface, (255, 255, 255), (0, y), (w, y))
You have to align the position to the grids size. Use the floor division operator (//) to divide the coordinates by the size of a cell and compute the integral index in the grid:
x, y = pygame.mouse.get_pos()
ix = x // sizebtwn
iy = y // sizebtwn
Multiply the result by the size of a cell to compute the coordinate:
self.cx, self.cy = ix * sizebtwn, iy * sizebtwn
Minimal example:
import pygame
pygame.init()
screen = pygame.display.set_mode((200, 200))
clock = pygame.time.Clock()
def drawgrid(w, rows, surface):
sizebtwn = w // rows
for i in range(0, w, sizebtwn):
x, y = i, i
pygame.draw.line(surface, (255, 255, 255), (x, 0), (x, w))
pygame.draw.line(surface, (255, 255, 255), (0, y), (w, y))
class Cube:
def update(self, sizebtwn):
x, y = pygame.mouse.get_pos()
ix = x // sizebtwn
iy = y // sizebtwn
self.cx, self.cy = ix * sizebtwn, iy * sizebtwn
self.square = pygame.Rect(self.cx, self.cy, sizebtwn, sizebtwn)
def draw(self, surface):
click = pygame.mouse.get_pressed()
if click[0]:
pygame.draw.rect(surface, (255, 255, 255), self.square)
cube = Cube()
run = True
while run:
clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
cube.update(screen.get_width() // 10)
screen.fill(0)
drawgrid(screen.get_width(), 10, screen)
cube.draw(screen)
pygame.display.flip()

Categories