I tried using the code so I can run a simulation of an object hitting on the ground but it just says
draw_polygon ([Vec2d(55.0, -4779353554820.233), Vec2d(55.0, -4779353554810.233), Vec2d(45.0, -4779353554810.233), Vec2d(45.0, -4779353554820.233)], 0.0, SpaceDebugColor(r=44.0, g=62.0, b=80.0, a=255.0), SpaceDebugColor(r=52.0, g=152.0, b=219.0, a=255.0))
import pymunk
#This comands sets the scene for our prosomition
space=pymunk.Space()
space.gravity = 0,-9.80665
body = pymunk.Body()
body.position= 50,100
#This comands create a box that attaches to the body and creates its settings
poly = pymunk.Poly.create_box(body)
poly.mass = 10
space.add(body, poly)
#Creates and prints the scene
print_options = pymunk.SpaceDebugDrawOptions()
speed=int(input("Speed:"))
while True:
space.step(speed)
space.debug_draw(print_options)
Im trying to run this on my visual studio but it's just saying:
draw_polygon ([Vec2d(55.0, -4779353554820.233), Vec2d(55.0, -4779353554810.233), Vec2d(45.0, -4779353554810.233), Vec2d(45.0, -4779353554820.233)], 0.0, SpaceDebugColor(r=44.0, g=62.0, b=80.0, a=255.0), SpaceDebugColor(r=52.0, g=152.0, b=219.0, a=255.0))
Is there any package for an graphical enviroment ?
Yes, by default the debug drawing will just print out the result (its made in this way so that you can use it without installing anything else and even run it from the terminal).
However, it also comes with a module for the two libraries pygame and pyglet that are documented here:
http://www.pymunk.org/en/latest/pymunk.pygame_util.html
and here
http://www.pymunk.org/en/latest/pymunk.pyglet_util.html
Both work in more or less the same way, just use their implementation of the SpaceDebugDrawOptions class instead of the default one.
An example of your code converted to pygame is below. Note that in your example you have speed (the input to space.step) set to an integer. However, when displaying its too big step size to see anything. I have adjusted it to speed/50 so if you enter 1 as speed, then it will progress in the speed matching pygame clock (clock.tick(50)). Without this the box moves too quickly out of the window:
import pygame
import pymunk
import pymunk.pygame_util
speed=int(input("Speed:"))
pygame.init()
screen = pygame.display.set_mode((600, 600))
clock = pygame.time.Clock()
running = True
### Physics stuff
space = pymunk.Space()
space.gravity = 0,-9.80665
body = pymunk.Body()
body.position= 50,100
#This comands create a box that attaches to the body and creates its settings
poly = pymunk.Poly.create_box(body)
poly.mass = 10
space.add(body, poly)
#Creates and prints the scene
print_options = pymunk.pygame_util.DrawOptions(screen)
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE:
running = False
### Draw stuff
screen.fill(pygame.Color("white"))
space.step(float(speed) / 50)
space.debug_draw(print_options)
### Flip screen
pygame.display.flip()
clock.tick(50)
pygame.display.set_caption("fps: " + str(clock.get_fps()))
Related
I'm currently working on a project based on pygame. It is the first time I'm attempting a project like this. I choose to try the pygmae_gui library in order to (who wold have guessed) implement a GUI to the project.
I successfully added some buttons to the application without any problems. I wrote a part where a new surface pops up when a certain button is pressed (which works without issues).
I want to add buttons on this new surface, but i don't know how.
My code looks something like this:
def _set_up_surfaces():
screen = pygame.display.set_mode((self.width, self.height))
background = pygame.Surface((self.width, self.height))
new_layer = pygame.Surface((440, 360))
def _set_up_click_button():
start_button_rect = pygame.Rect(0, 0, 150, 30)
bye_button_layout_rect = pygame.Rect(0, 0, 150, 30)
bye_button_layout_rect.bottomright = (-30, -20)
close_button_rect = pygame.Rect(320, 320, 150, 30)
start_button = pygame_gui.elements.UIButton(relative_rect=start_button_rect, text="START",manager=gui_manager)
new_layer_close_button = pygame_gui.elements.UIButton(relative_rect=close_button_rect, text='close', manager=self.gui_manager, container=new_layer)
active = True
# set up start display:
new_layer_visible = False
set_up_surfaces()
set_up_click_button()
# main game loop
while active:
for event in pygame.event.get():
if event.type == pygame.QUIT:
active = False
if event.type == pygame_gui.UI_BUTTON_PRESSED:
if event.ui_element == self.start_button:
self.machine_visible = True
if event.ui_element == self.bye_button:
print('Good Bye!')
active = False
self.gui_manager.process_events(event)
if new_layer_visible:
new_layer_visible.blit(imported_drawing, (0, 0))
self.background.blit(new_layer, (140, 60))
gui_manager.update(self.time_delta)
screen.blit(self.background, (0, 0))
gui_manager.draw_ui(self.screen)
pygame.display.update()
I know that the code does not run as I wrote it here since I only included the part I thought is relevant.
I tried to set the container argument to the surface as I saw as a suggestion online but I got an Error as response:
ValueError: container parameter must be of type IContainerLikeInterface.
The objective is to put the "close-Button" on the new_layer surface. Is this possible using pygame_gui, should I use a different library?
You cannot add a Pygame GUI button to a pygame.Surface object because a pygame.Surface consists only of a grid of pixels and cannot contain objects. Also, the Pygame GUI is built on top of Pygame, not the other way around, so a Pygame object cannot handle a Pygame GUI object and no Pygame object implements the interface IContainerLikeInterface. You have to draw the Surface manually in the background and put the GUI on top of it.
I am trying to write a little digits game using pygame. The idea of the game is to guess the four-digit number randomly chosen by computer. But I am stuck at the very beginning I started by creating all the essential elements: colours, fonts, surfaces, etc. I used blit to 'simulate' computer choice and to show the user's guess. And interestingly enough, not all the inputs are displayed. E.g. '1234' and '9999' is displayed. However, '5738' and '7365' are not. Looking forward to hearing opinions of the experienced users.
import random
import pygame
pygame.init()
width = 900
height = 500
black = (0,0,0)
pastel_blue = (200,205,230)
win = pygame.display.set_mode((width,height))
pygame.display.set_caption("Bulls and Cows")
digit_font = pygame.font.SysFont('comicsans', 30)
a = (random.randint(1000, 10000))
print(a)
def display():
win.fill((pastel_blue))
number = digit_font.render("_ _ _ _", 1, black)
win.blit(number, (width//2-number.get_width()//2, height//4))
pygame.display.update()
display()
def guess_number():
global c
c = input("Guess the number: ")
guess_number()
def guess_display():
text = digit_font.render(c, 1, black)
print(text.get_width()//2)
win.blit(text, [width//2-text.get_width()/2, 300]) #this seems to be the part that doesn't work correctly
pygame.display.update()
pygame.time.delay(2000)
guess_display()
You have to handle the events in the application loop. See pygame.event.get() respectively pygame.event.pump():
For each frame of your game, you will need to make some sort of call to the event queue. This ensures your program can internally interact with the rest of the operating system.
def guess_display():
text = digit_font.render(c, 1, black)
print(text.get_width()//2)
win.blit(text, [width//2-text.get_width()/2, 300]) #this seems to be the part that doesn't work correctly
pygame.display.update()
pygame.event.pump() # <---
pygame.time.delay(2000)
However, the usual way is to use an application loop. Also see Why is my PyGame application not running at all?:
def guess_display():
text = digit_font.render(c, 1, black)
print(text.get_width()//2)
run = True
while run:
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
win.blit(text, [width//2-text.get_width()/2, 300])
pygame.display.update()
Also see:
Why is my display not responding while waiting for input?
Why does pygame.display.update() not work if an input is directly followed after it?
How to create a text input box with pygame?
I need to to build an application that has multiple windows. In one of these windows, I need to be able to play a simple game and another window has to display questions and get response from a user that influences the game.
(1) I was wanting to use pygame in order to make the game. Is there a simple way to have pygame operate with multiple windows?
(2) If there is no easy way to solve (1), is there a simple way to use some other python GUI structure that would allow for me to run pygame and another window simultaneously?
The short answer is no, creating two pygame windows in the same process is not possible (as of April 2015). If you want to run two windows with one process, you should look into pyglet or cocos2d.
An alternative, if you must use pygame, is to use inter-process communication. You can have two processes, each with a window. They will relay messages to each other using sockets. If you want to go this route, check out the socket tutorial here.
Internally set_mode() probably sets a pointer that represents the memory of a unique display. So if we write:
screenA = pygame.display.set_mode((500,480), 0, 32)
screenB = pygame.display.set_mode((500,480), 0, 32)
For instance we can do something like that later:
screenA.blit(background, (0,0))
screenB.blit(player, (100,100))
both blit() calls will blit on the same surface. screenA and screenB are pointing to the same memory address. Working with 2 windows is quite hard to achieve in pygame.
Yes, that is possible. SDL2 is able to open multiple windows. In the example folder you can take a look at "video.py".
https://github.com/pygame/pygame/blob/main/examples/video.py
"This example requires pygame 2 and SDL2. _sdl2 is experimental and will change."
I've been trying to do this for a few days now, and I'm finally making progress. Does this count as simple? Or even as "being in" pygame. In this exampe I never even call pygame.init() That just seems to get in the way. The event pump is running (for mouse and keyboard) but not all the normal events seem to be coming thru (FOCUSGAINED and LOST in particular). In this example each window renders it status (size, position, etc) to it's self. I also have versions where I mix SDL windows with the pygame display. But those involve encapsulating a Window rather than extending it.
In order to draw on these windows you can draw on a vanilla surface as usually and then use the Renderer associated with the window to create a texture that will update the the window. (texture.draw(), renderer.present). You dont't use display.update() or flip() because you you aren't using the pygame display surface.
The X11 package is just my experimental windowing stuff and has nothing to do with X11. I think all my imports are explicit so it should be easy to figure out what the missing pieces are.
from typing import List
from pygame import Rect, Surface, Color
import pygame.event
from pygame.event import Event
from pygame.freetype import Font
from pygame._sdl2.video import Window, Renderer, Texture
from X11.windows import DEFAULT_PAD, default_font, window_info
from X11.text import prt
class MyWindow(Window):
def __init__(self, font: Font=None):
super().__init__()
self._font = font if font else default_font()
self.resizable = True
self._renderer = None
def destroy(self) -> None:
super().destroy()
def update(self):
r = self.renderer
r.draw_color = Color('grey')
r.clear()
#self.render_line(f"TICKS: {pg.time.get_ticks()}", 5, size=16.0)
txt: List[str] = window_info(self)
self.render_text(txt, lineno=0)
r.present()
#property
def renderer(self):
if self._renderer is None:
try:
self._renderer = Renderer.from_window(self)
except:
self._renderer = Renderer(self)
return self._renderer
def render_text(self, txt: List[str], lineno: int=0):
for line in txt:
self.render_line(line, lineno, size=16.0)
lineno += 1
def render_line(self, txt: str, lineno: int = 0, size: float = 0.0):
font = self._font
line_spacing = font.get_sized_height(size) + DEFAULT_PAD
x = DEFAULT_PAD
y = DEFAULT_PAD + lineno * line_spacing
# compute the size of the message
src_rect = font.get_rect(txt, size=size)
# create a new surface (image) of text
l_surf = Surface((src_rect.width, src_rect.height))
src_rect = font.render_to(l_surf, (0, 0), txt, size=size)
# get ready to draw
texture = Texture.from_surface(self.renderer, l_surf)
dst = Rect(x, y, src_rect.width, src_rect.height)
texture.draw(None, dst)
_running: bool = False
def test():
global _running
win1 = MyWindow()
win2 = MyWindow()
my_windows = {win1.id: win1, win2.id: win2}
win = win1
rnd = win1.renderer
print("pygame.get_init():", pygame.get_init())
print("pygame.display.get_init():", pygame.display.get_init())
print("pygame.mouse.get_pos():", pygame.mouse.get_pos())
clock = pygame.time.Clock()
_running = True
while _running:
events = pygame.event.get()
for event in events:
if event.type != pygame.MOUSEMOTION:
print(event)
if event.type == pygame.QUIT:
_running = False
elif event.type == pygame.WINDOWENTER:
win = my_windows[event.window.id]
print(f"Enter Window ({event.window.id}")
elif event.type == pygame.WINDOWLEAVE:
pass
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_q:
_running = False
if event.key == pygame.K_1:
win = my_windows[1]
rnd = win.renderer
if event.key == pygame.K_2:
win = my_windows[2]
rnd = win.renderer
elif event.key == pygame.K_b:
rnd.draw_color = Color('blue')
rnd.clear()
elif event.key == pygame.K_g:
rnd.draw_color = Color('grey')
rnd.clear()
elif event.key == pygame.K_t:
win.render_line("Hello, world")
elif event.key == pygame.K_s:
surface = pygame.display.get_surface()
print("surface: ", surface)
elif event.key == pygame.K_f:
pygame.display.flip()
# pygame.error: Display mode not set
elif event.key == pygame.K_u:
pygame.display.update()
# pygame.error: Display mode not set
for win in my_windows.values():
win.update()
clock.tick(40)
if __name__ == '__main__':
test()
I am using python64 bit. I have created the map which is consists of 4-5 shape files, take the Image file(.bmp) of it & opened in to the python. Now I want to display all the coordinates(longitude , latitude) where pointer moves on the Image. I have used the following code.
import pygame
import math
pygame.display.init()
window = pygame.display.set_mode((1576, 847))
mapImg = pygame.image.load("gis12.bmp")
one = False
while not done:
window.fill((0,0,0))
evtList = pygame.event.get()
for evt in evtList:
if evt.type == pygame.QUIT:
done = True
window.blit(mapImg, (0,0))
pygame.display.update()
pygame.quit()'
I have a block of code that worked outside of a function, but not inside.
I also made sure the necessary variables were global.
I can get the width of the surface using chair.get_width() inside the function and it works fine, but I cannot execute screen.blit(chair, (10,10)) for some reason. I don't get an error, it just doesn't do anything...
Here is my script (it creates a window, then calls a function every 100 milliseconds that gets the mouse position, rotates an image x degrees and then blits (or should blit) the image to the window):
cif = "images/chair3.png"
import pygame, sys
from pygame.locals import *
pygame.init()
screen = pygame.display.set_mode((640,480),0,32)
chair = pygame.image.load(cif).convert_alpha()
pygame.time.set_timer(USEREVENT + 1, 100)
def cursor(speed):
global i
global chair
global screen
x,y = pygame.mouse.get_pos()
x -= chair.get_width()/2
y -= chair.get_height()/2
if i < 360:
i = i + 360/(1000/speed)
else:
i = 0
orig_chair_rect = chair.get_rect()
chair1 = pygame.transform.rotate(chair, i);
rot_chair_rect = orig_chair_rect.copy()
rot_chair_rect.center = chair1.get_rect().center
chair1 = chair1.subsurface(rot_chair_rect).copy()
print chair.get_width()
screen.blit(chair1,(x,y))
while True:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
if event.type == USEREVENT + 1:
cursor(50)
You do need to use pygame.display.flip() or pygame.display.update(), the screen will never update if you don't, and therefore your chair will not be blitted onto the screen.
Tried it, it works. If it doesn't work for you, reinstall Pygame, and try again.
You need to call pygame.display.flip() at the end of your function -- otherwise, your drawing never gets copied from the backbuffer to the live display.