Static object with pymunk and pygame not working - python

I wrote a python game using pygame and pymunk, but the playground() section doesnt work. It supposed to show a static object, but it doesnt. I asked and it was supposed to interact with balls being dropped.
heres the code:
import pygame, sys
import pymunk
import pymunk.pygame_util
from pymunk.vec2d import Vec2d
size = (800, 600)
FPS = 120
space = pymunk.Space()
space.gravity = (0,250)
pygame.init()
screen = pygame.display.set_mode(size)
clock = pygame.time.Clock()
class Ball:
global space
def __init__(self, pos):
self.body = pymunk.Body(1,1, body_type = pymunk.Body.DYNAMIC)
self.body.position = pos
self.radius = 60
self.shape = pymunk.Circle(self.body, self.radius)
space.add(self.body, self.shape)
# INDENTATION
#<--|
def draw(self):
x = int(self.body.position.x)
y = int(self.body.position.y)
pygame.draw.circle(screen, (255,0,0), (x,y), self.radius)
def playground():
body = pymunk.Body(1,1, body_type = pymunk.Body.STATIC)
balls = []
balls.append(Ball((400,0)))
balls.append(Ball((100,0)))
balls.append(Ball((600,100)))
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
if event.type == pygame.MOUSEBUTTONDOWN:
balls.append(Ball(event.pos))
# INDENTATION
#<------|
screen.fill((217,217,217))
for ball in balls:
ball.draw()
playground()
space.step(1/50)
pygame.display.update()
clock.tick(FPS)
Any solution?
Its for a school project so any help will greated.
Thanks.

You forgot to add the body into the space, that's why the balls kept on falling.
You also need to define the shape of the body which is a required argument in adding to space. Lastly, you need to draw into pygame screen the shape as previously defined.
def playground():
body = pymunk.Body(1,1, body_type = pymunk.Body.STATIC)
polygon_points = [(0,580),(800,580),(800,600),(0,600)]
shape = pymunk.Poly(space.static_body, polygon_points)
space.add(body, shape)
pygame.draw.polygon(screen, (0, 0, 0), polygon_points)

Related

Pygame .blit() not working in class, or in game loop

I was following a pygame tutorial, tested to see if the player blit was working and it wasnt, checked for problems but there were none that I could find, and then I tested a .blit() directly in the game loop and that didnt work so I've been stumped for a good bit now.
player class below, "Player_Down" should be irrelevant rn since its just an image
class Player():
def __init__(self, x, y):
direction = "down"
self.image = player_down
self.rect = self.image.get_rect()
self.rect.center = (x, y)
def draw(self):
screen.blit(self.image, self.rect)
ply = Player(SCREEN_WIDTH // 2 , SCREEN_HEIGHT - 150)
Game loop with draw function called
running = True
while running:
screen.fill((83,90,83))
ply.draw()
#event handler
for event in pygame.event.get():
if event.type == pygame.QUIT:
print("Game quit via X button")
running = False
pygame.display.update()
There is no problem with the code in the question. Your suspicion that blit does not work is wrong (alos see How to draw images and sprites in pygame?). The code works fine.
However, I suggest passing the screen Surface as an argument to draw method. See the minimal and working example:
import pygame
pygame.init()
SCREEN_WIDTH, SCREEN_HEIGHT = 400, 400
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
player_down = pygame.Surface((30, 30))
player_down.fill((255, 0, 0))
class Player():
def __init__(self, x, y):
direction = "down"
self.image = player_down
self.rect = self.image.get_rect()
self.rect.center = (x, y)
def draw(self, surf):
surf.blit(self.image, self.rect)
ply = Player(SCREEN_WIDTH // 2 , SCREEN_HEIGHT - 150)
running = True
while running:
#event handler
for event in pygame.event.get():
if event.type == pygame.QUIT:
print("Game quit via X button")
running = False
screen.fill((83,90,83))
ply.draw(screen)
pygame.display.update()
pygame.quit()
exit()

Pygame - creating a rotating projectile arount the center [duplicate]

This code is mostly just the generic start up of a pygame window but I'm trying to make it so the object moves (the planet object I've made) in the orbit around the sun object I've made for the coordinates I've given it. I know the x and y values are updating but I don't understand why the object doesn't move.
#import the library
import pygame
import math
#classes
class button:
def _init_ (self,screen, colour, x, y, width,height, letter):
self.screen = screen
self.colour = colour
self.x = x
self.y = y
self.width = width
self.height = height
self.letter = letter
self.radius = radius
def draw(self):
pygame.draw.rect(self.screen, self.colour,(self.x,self.y, self.width, self.height))
if self.letter!= '+' and self.letter!= '-':
font = pygame.font.SysFont('agencyfb',15,True,False)
else:
font = pygame.font.SysFont('agencyfb',25,True,False)
text = font.render(self.letter, True, black)
text_rect = text.get_rect(center=(self.x+self.width/2,self.y+self.height/2))
screen.blit(text, text_rect)
class orbit:
def __init__(self,screen,colour,x,y,radius,width):
self.screen = screen
self.colour = colour
self.x = x
self.y = y
self.width = width
self.radius = radius
def draw_circle(self):
pygame.draw.circle(self.screen,self.colour,(self.x,self.y),self.radius,self.width)
#define colours
##Sun = pygame.draw.circle(screen,Sun,[1000,450],100,0)
Black = (0,0,0)
White = (255,255,255)
Green = (0,255,0)
Red = (255,0,0)
Blue = (0,0,255)
Sun = (255,69,0)
Sun = []
Planet = []
#initialise the engine
pygame.init()
#Opening a window
size = (1920,1080)
screen = pygame.display.set_mode(size)
#set window title
pygame.display.set_caption("Orbit Simulator")
#loop unti the user clicks the close button
done = False
#
x=1000
y=450
Sun.append(orbit(screen,Red,1000,450,100,0))
Planet.append(orbit(screen,White,x,y,50,0))
#
#used to manage how fast the screen updates
clock = pygame.time.Clock()
#------ Main program Loop ------
while not done:
#--- Main event loop
for event in pygame.event.get(): #user did something
if event.type == pygame.QUIT: #if user clicked close
done = True #flag that we are done and exit the loop
#------ Game logic should go here ------
#------ Drawing code should go here -------
#first, clear the screen to white. Don't put other drawing commands above this or they will be erased with this command.
screen.fill(Black)
for i in Sun:
i.draw_circle()
for i in Planet:
r=150
angle=0
count = 0
while angle <= 360:
angle_radians = math.radians(angle)
x = int(math.cos(angle_radians)*r)
y = int(math.sin(angle_radians)*r)
angle +=1
count +=1
print(count)
x+=1000
y+=450
pygame.draw.circle(screen,White,[x,y],10,0)
print("Position [",x,",",y,"]")
#update the screen
pygame.display.flip()
#------ Limit to 60 frames per second ------
clock.tick(60)
#------ When the loop ends, quit ------
pygame.quit()
You can make an object rotate around another by using trigonometry or vectors. With vectors you just have to rotate a vector which defines the offset from the rotation center each frame and add it to the position vector (self.pos which is the rotation center) to get the desired self.rect.center coordinates of the orbiting object.
import pygame as pg
from pygame.math import Vector2
class Planet(pg.sprite.Sprite):
def __init__(self, pos, *groups):
super().__init__(*groups)
self.image = pg.Surface((40, 40), pg.SRCALPHA)
pg.draw.circle(self.image, pg.Color('dodgerblue'), (20, 20), 20)
self.rect = self.image.get_rect(center=pos)
self.pos = Vector2(pos)
self.offset = Vector2(200, 0)
self.angle = 0
def update(self):
self.angle -= 2
# Add the rotated offset vector to the pos vector to get the rect.center.
self.rect.center = self.pos + self.offset.rotate(self.angle)
def main():
pg.init()
screen = pg.display.set_mode((640, 480))
screen_rect = screen.get_rect()
clock = pg.time.Clock()
all_sprites = pg.sprite.Group()
planet = Planet(screen_rect.center, all_sprites)
yellow = pg.Color('yellow')
while True:
for event in pg.event.get():
if event.type == pg.QUIT:
return
all_sprites.update()
screen.fill((30, 30, 30))
pg.draw.circle(screen, yellow, screen_rect.center, 60)
all_sprites.draw(screen)
pg.display.flip()
clock.tick(60)
if __name__ == '__main__':
main()
pg.quit()

Sprites not showing in Pygame

I'm not sure what I am doing wrong here. There are no errors appearing but when the game loads nothing appears, just the black background. This is the code that I am running for loading my sprite into the game.
import pygame
import sys
import os
pygame.init()
"""
Spawn Player
"""
class Player(pygame.sprite.Sprite):
pygame.display.set_mode()
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.images = []
img = pygame.image.load(os.path.join("images", "ninja.jpeg")).convert()
self.images.append(img)
self.image = self.images[0]
self.rect = self.image.get_rect()
def Run(self):
pygame.sprite.Sprite.__init__(self)
self.images = []
for i in range(1,5):
run_img = pygame.image.load(os.path.join("run","ninja_run" + str(i) + ".jpeg")).convert()
self.images.append(run_img)
self.image = self.images[0]
self.rect = self.image.get_rect()
"""
Setup
"""
worldx = 900
worldy = 700
fps = 40
ani = 4
clock = pygame.time.Clock()
world = pygame.display.set_mode([worldx, worldy])
player = Player()
player.rect.x = 32
player.rect.y = 32
player_list = pygame.sprite.Group()
player_list.add(player)
BLUE = (25, 25, 200)
BLACK = (20, 20, 20)
WHITE = (255, 255, 255)
RED = (200, 25, 25)
"""
Main Loop
"""
main = True
while main:
pygame.time.delay(100)
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
break
#world.blit(backdrop, backdrop_box)
player_list.draw(world)
world.fill(BLACK)
pygame.display.flip()
clock.tick(fps)
I had a friend look over the code and he said there is a problem with the init under the player class but aside from that I really do not understand where the problem within the code is.
The window is calling properly and I'm getting the background as black but the sprite simply will not load.
I'm working with this tutorial here to get the sprites to show up. I already have the movement among other parts setup the only thing that doesn't seem to be working is the code revolving around the sprites.
Any help here would be great.
You do world.fill(BLACK) immediately for pygame.display.flip().
world.fill(BLACK) fills the entire window surface in black and covers everything which was drawn before. pygame.display.flip() updates the window. This causes that the window is appears completely black.
Change the order of the instructions to solve the issue:
world.fill(BLACK)
player_list.draw(world)
# world.fill(BLACK) <---- delete
pygame.display.flip()

module object is not callable in pygame

import pygame
import snake
pygame.init()
# Set the height and width of the screen
screen = pygame.display.set_mode((800,600))
pygame.display.set_caption("Snake")
quit = False
clock = pygame.time.Clock()
snake = snake.Snake()
while not quit:
clock.tick(30)
for event in pygame.event.get():
if event.type == pygame.QUIT:
quit = True # Flag that we are done so we exit this loop
# rectangle = pygame.Rect(400, 150, 100, 60) #first two = x and y coords
# pygame.draw.rect(screen, [0, 0, 255], rectangle)
snake.draw(screen)
pygame.display.update()
# Be IDLE friendly
pygame.quit()
import pygame
BODY_DIM = 50 #dimension for each part of the snake's body
RED = [255, 0, 0]
class Snake:
#represent the snake as a list of squares
class BodyNode:
def __init__(self, coords):
self.body = pygame.Rect(coords, (BODY_DIM, BODY_DIM))
def __init__(self):
self.snake_body = [Snake.BodyNode((50, 50))]
def draw(self, screen):
for s in self.snake_body:
pygame.draw().rect(screen, RED, s.body)
These are two separate files the bottom one with the import pygame statement is in a file called Snake.py. This line seems to be the issue: pygame.draw().rect(screen, RED, s.body), I can't seem to find out why though. the pygame was imported so it should work.
you need to remove the brackets
pygame.draw().rect(screen,RED,s.body)
# ^^ HERE
that way you are not calling a module

Python Pygame image not displaying

I am trying to display a game in pygame. But it won't work for some reason, any ideas? Here is my code:
import pygame, sys
from pygame.locals import *
pygame.init()
screen=pygame.display.set_mode((640,360),0,32)
pygame.display.set_caption("My Game")
p = 1
green = (0,255,0)
pacman ="imgres.jpeg"
pacman_x = 0
pacman_y = 0
while True:
pacman_obj=pygame.image.load(pacman).convert()
screen.blit(pacman_obj, (pacman_x,pacman_y))
blue = (0,0,255)
screen.fill(blue)
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
if event.type==KEYDOWN:
if event.key==K_LEFT:
p=0
pygame.display.update()
Just a guess, as I haven't actually ran this:
Is the screen just showing up blue and you're missing the pacman image? What might be happening is that you are blitting pacman onto the screen, and then doing a screen.fill(blue), which is essentially overwriting your pacman image with blue. Try reversing these steps in your code (that is, filling the screen blue, then blitting pacman after).
if the screen shows up blue, it is because you need to "blit" the image after you do screen.fill
also, blue has to be defined at the top, and it should be in a different loop. here is how i would do it:
import pygame, sys
from pygame.locals import *
pygame.init()
screen=pygame.display.set_mode((640,360),0,32)
pygame.display.set_caption("My Game")
p = 1
green = (0,255,0)
blue = (0,0,255)
pacman ="imgres.jpeg"
pacman_x = 0
pacman_y = 0
pacman_obj=pygame.image.load(pacman).convert()
done = False
clock=pygame.time.Clock()
while done==False:
for event in pygame.event.get():
if event.type == pygame.QUIT:
done=True
if event.type==KEYDOWN:
if event.key==K_LEFT:
p=0
screen.fill(blue)
screen.blit(pacman_obj, (pacman_x,pacman_y))
pygame.display.flip()
clock.tick(100)
pygame.quit()
Note:
You are creating a new image every frame. This is slow.
Coordinates for blit can be Rect()s
Here's updated code.
WINDOW_TITLE = "hi world - draw image "
import pygame
from pygame.locals import *
from pygame.sprite import Sprite
import random
import os
class Pacman(Sprite):
"""basic pacman, deriving pygame.sprite.Sprite"""
def __init__(self, file=None):
"""create surface"""
Sprite.__init__(self)
# get main screen, save for later
self.screen = pygame.display.get_surface()
if file is None: file = os.path.join('data','pacman.jpg')
self.load(file)
def draw(self):
"""draw to screen"""
self.screen.blit(self.image, self.rect)
def load(self, filename):
"""load file"""
self.image = pygame.image.load(filename).convert_alpha()
self.rect = self.image.get_rect()
class Game(object):
"""game Main entry point. handles intialization of game and graphics, as well as game loop"""
done = False
color_bg = Color('seagreen') # or also: Color(50,50,50) , or: Color('#fefefe')
def __init__(self, width=800, height=600):
"""Initialize PyGame window.
variables:
width, height = screen width, height
screen = main video surface, to draw on
fps_max = framerate limit to the max fps
limit_fps = boolean toggles capping FPS, to share cpu, or let it run free.
color_bg = backround color, accepts many formats. see: pygame.Color() for details
"""
pygame.init()
# save w, h, and screen
self.width, self.height = width, height
self.screen = pygame.display.set_mode(( self.width, self.height ))
pygame.display.set_caption( WINDOW_TITLE )
# fps clock, limits max fps
self.clock = pygame.time.Clock()
self.limit_fps = True
self.fps_max = 40
self.pacman = Pacman()
def main_loop(self):
"""Game() main loop.
Normally goes like this:
1. player input
2. move stuff
3. draw stuff
"""
while not self.done:
# get input
self.handle_events()
# move stuff
self.update()
# draw stuff
self.draw()
# cap FPS if: limit_fps == True
if self.limit_fps: self.clock.tick( self.fps_max )
else: self.clock.tick()
def draw(self):
"""draw screen"""
# clear screen."
self.screen.fill( self.color_bg )
# draw code
self.pacman.draw()
# update / flip screen.
pygame.display.flip()
def update(self):
"""move guys."""
self.pacman.rect.left += 10
def handle_events(self):
"""handle events: keyboard, mouse, etc."""
events = pygame.event.get()
for event in events:
if event.type == pygame.QUIT: self.done = True
# event: keydown
elif event.type == KEYDOWN:
if event.key == K_ESCAPE: self.done = True
if __name__ == "__main__":
game = Game()
game.main_loop()
First you blit the image and then fill it with BLUE ,so it might show only blue screen ,
Solution: First fill screen blue and then blit it.
import pygame, sys
from pygame.locals import *
pygame.init()
screen=pygame.display.set_mode((640,360),0,32)
pygame.display.set_caption("My Game")
p = 1
green = (0,255,0)
pacman ="imgres.jpeg"
pacman_x = 0
pacman_y = 0
while True:
pacman_obj=pygame.image.load(pacman).convert()
blue = (0,0,255)
screen.fill(blue) # first fill screen with blue
screen.blit(pacman_obj, (pacman_x,pacman_y)) # Blit the iamge
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
if event.type==KEYDOWN:
if event.key==K_LEFT:
p=0
pygame.display.update()

Categories

Resources