In ursina, How can I save the render frames as a sequence of images or a video? Ursina cheat sheet has nothing on this.
You can see VideoRecorder :
from ursina import *
import os, shutil
import numpy as np
# import imageio # gets imported in convert_to_gif
# from panda3d.core import PNMImage
class VideoRecorder(Entity):
def __init__(self, duration=5, name='untitled_video', **kwargs):
super().__init__()
self.recording = False
self.file_path = Path(application.asset_folder) / 'video_temp'
self.i = 0
self.duration = duration
self.fps = 30
self.video_name = name
self.t = 0
for key, value in kwargs.items():
setattr(self, key, value)
self.max_frames = int(self.duration * self.fps)
self.frames = []
def start_recording(self):
print('start recording,', self.duration, self.file_path)
window.fps_counter.enabled = False
window.exit_button.visible = False
self.frames = []
self.max_frames = self.duration * self.fps
if not self.file_path.exists():
self.file_path.mkdir()
base.movie(namePrefix=f'\\video_temp\\{self.video_name}', duration=2.0, fps=30, format='png', sd=4)
self.recording = True
invoke(self.stop_recording, delay=self.duration)
def stop_recording(self):
self.recording = False
window.fps_counter.enabled = True
window.exit_button.visible = True
print('stop recording')
self.convert_to_gif()
def update(self):
if not self.recording:
return
self.t += time.dt
if self.t >= 1/30:
base.screenshot(
namePrefix = '\\video_temp\\' + self.video_name + '_' + str(self.i).zfill(4) + '.png',
defaultFilename = 0,
)
self.t = 0
# # self.frames.append(self.renderToPNM())
# image = base.win.getScreenshot()
# data = image.getRamImageAs("RGB").getData()
# # from PIL import Image
# # image = Image.fromarray(data)
# # img = data.convert("RGBA")
# data = np.array(data)
#
# # image = deepcopy(camera.render_texture)
# self.frames.append(data)
self.i += 1
# store screenshot in memory
# def renderToPNM(self):
# base.graphicsEngine.renderFrame()
# if hasattr(camera, 'render_texure'):
# return copy(camera.render_texure)
# # image = PNMImage()
# # dr = base.camNode.getDisplayRegion(0)
# # dr.getScreenshot(image)
# # win.setupRenderTexture()
# return None
def convert_to_gif(self):
import imageio
images = []
if not os.path.exists(self.file_path):
return
for filename in os.listdir(self.file_path):
images.append(imageio.imread(self.file_path/filename))
imageio.mimsave(Path(f'{self.file_path.parent}/{self.video_name}.gif'), images)
shutil.rmtree(self.file_path) # delete temp folder
print('saved gif to:', Path(f'{self.file_path.parent}/{self.video_name}.gif'))
class VideoRecorderUI(WindowPanel):
def __init__(self, **kwargs):
self.duration_label = Text('duration:')
self.duration_field = InputField(default_value='5')
self.fps_label = Text('fps:')
self.fps_field = InputField(default_value='30')
self.name_label = Text('name:')
self.name_field = InputField(default_value='untitled_video')
self.start_button = Button(text='Start Recording [Shift+F12]', color=color.azure, on_click=self.start_recording)
super().__init__(
title='Video Recorder [F12]',
content=(
self.duration_label,
self.duration_field,
self.fps_label,
self.fps_field,
self.name_label,
self.name_field,
Space(1),
self.start_button,
),
)
self.y = .5
self.scale *= .75
self.visible = False
def input(self, key):
if key == 'f12':
self.visible = not self.visible
if held_keys['shift'] and key == 'f12':
self.start_button.on_click()
def start_recording(self):
print(self.name_field)
if self.name_field.text == '':
self.name_field.blink(color.color(0,1,1,.5), .5)
print('enter name')
return
# self.start_button.color=color.lime
self.visible = False
application.video_recorder.duration = float(self.duration_field.text)
application.video_recorder.video_name = self.name_field.text
application.video_recorder.frame_skip = 60 // int(self.fps_field.text)
application.video_recorder.recording = True
if __name__ == '__main__':
app = Ursina()
# window.size = (1600/3,900/3)
# cube = primitives.RedCube()
# cube.animate_x(5, duration=5, curve=curve.linear)
# cube.animate_x(0, duration=5, curve=curve.linear, delay=5)
# vr = VideoRecorder()
# invoke(setattr, vr, 'recording', True, delay=1)
# invoke(os._exit, 0, delay=6)
# vr.recording = True
window.size *= .5
from ursina.prefabs.first_person_controller import FirstPersonController
from ursina.shaders import lit_with_shadows_shader
random.seed(0)
Entity.default_shader = lit_with_shadows_shader
ground = Entity(model='plane', collider='box', scale=64, texture='grass', texture_scale=(4,4))
editor_camera = EditorCamera(enabled=False, ignore_paused=True)
player = FirstPersonController(model='cube', z=-10, color=color.orange, origin_y=-.5, speed=8)
player.collider = BoxCollider(player, Vec3(0,1,0), Vec3(1,2,1))
gun = Entity(model='cube', parent=camera, position=(.5,-.25,.25), scale=(.3,.2,1), origin_z=-.5, color=color.red, on_cooldown=False)
shootables_parent = Entity()
mouse.traverse_target = shootables_parent
for i in range(16):
Entity(model='cube', origin_y=-.5, scale=2, texture='brick', texture_scale=(1,2),
x=random.uniform(-8,8),
z=random.uniform(-8,8) + 8,
collider='box',
scale_y = random.uniform(2,3),
color=color.hsv(0, 0, random.uniform(.9, 1))
)
sun = DirectionalLight()
sun.look_at(Vec3(1,-1,-1))
Sky()
vr = VideoRecorder(duration=10)
def input(key):
if key == '5':
vr.start_recording()
if key == '6':
vr.stop_recording()
app.run()
This code will convert the recording to mp4 video:
from ursina import *
import os, shutil
import numpy as np
# import imageio # gets imported in convert_to_gif
# from panda3d.core import PNMImage
class VideoRecorder(Entity):
def __init__(self, duration=5, name='untitled_video', **kwargs):
super().__init__()
self.recording = False
self.file_path = Path(application.asset_folder) / 'video_temp'
self.i = 0
self.duration = duration
self.fps = 30
self.video_name = name
self.t = 0
for key, value in kwargs.items():
setattr(self, key, value)
self.max_frames = int(self.duration * self.fps)
self.frames = []
def start_recording(self):
print('start recording,', self.duration, self.file_path)
window.fps_counter.enabled = False
window.exit_button.visible = False
self.frames = []
self.max_frames = self.duration * self.fps
if not self.file_path.exists():
self.file_path.mkdir()
base.movie(namePrefix=f'\\video_temp\\{self.video_name}', duration=2.0, fps=30, format='png', sd=4)
self.recording = True
invoke(self.stop_recording, delay=self.duration)
def stop_recording(self):
self.recording = False
window.fps_counter.enabled = True
window.exit_button.visible = True
print('stop recording')
# self.convert_to_gif()
self.convert_to_vid()
def update(self):
if not self.recording:
return
self.t += time.dt
if self.t >= 1/30:
base.screenshot(
namePrefix = '\\video_temp\\' + self.video_name + '_' + str(self.i).zfill(4) + '.png',
defaultFilename = 0,
)
self.t = 0
self.i += 1
def convert_to_gif(self):
import imageio
images = []
if not os.path.exists(self.file_path):
return
for filename in os.listdir(self.file_path):
images.append(imageio.imread(self.file_path/filename))
imageio.mimsave(Path(f'{self.file_path.parent}/{self.video_name}.gif'), images)
shutil.rmtree(self.file_path) # delete temp folder
print('saved gif to:', Path(f'{self.file_path.parent}/{self.video_name}.gif'))
def convert_to_vid(self):
import imageio
images = []
if not os.path.exists(self.file_path):
return
writer = imageio.get_writer('test.mp4', fps=self.fps)
for file in os.listdir(self.file_path):
im = imageio.imread(self.file_path/file)
writer.append_data(im)
writer.close()
print('Video saved!!')
class VideoRecorderUI(WindowPanel):
def __init__(self, **kwargs):
self.duration_label = Text('duration:')
self.duration_field = InputField(default_value='5')
self.fps_label = Text('fps:')
self.fps_field = InputField(default_value='30')
self.name_label = Text('name:')
self.name_field = InputField(default_value='untitled_video')
self.start_button = Button(text='Start Recording [Shift+F12]', color=color.azure, on_click=self.start_recording)
super().__init__(
title='Video Recorder [F12]',
content=(
self.duration_label,
self.duration_field,
self.fps_label,
self.fps_field,
self.name_label,
self.name_field,
Space(1),
self.start_button,
),
)
self.y = .5
self.scale *= .75
self.visible = False
def input(self, key):
if key == 'f12':
self.visible = not self.visible
if held_keys['shift'] and key == 'f12':
self.start_button.on_click()
def start_recording(self):
print(self.name_field)
if self.name_field.text == '':
self.name_field.blink(color.color(0,1,1,.5), .5)
print('enter name')
return
# self.start_button.color=color.lime
self.visible = False
application.video_recorder.duration = float(self.duration_field.text)
application.video_recorder.video_name = self.name_field.text
application.video_recorder.frame_skip = 60 // int(self.fps_field.text)
application.video_recorder.recording = True
if __name__ == '__main__':
app = Ursina()
# window.size = (1600/3,900/3)
# cube = primitives.RedCube()
# cube.animate_x(5, duration=5, curve=curve.linear)
# cube.animate_x(0, duration=5, curve=curve.linear, delay=5)
# vr = VideoRecorder()
# invoke(setattr, vr, 'recording', True, delay=1)
# invoke(os._exit, 0, delay=6)
# vr.recording = True
window.size *= .5
from ursina.prefabs.first_person_controller import FirstPersonController
from ursina.shaders import lit_with_shadows_shader
random.seed(0)
Entity.default_shader = lit_with_shadows_shader
ground = Entity(model='plane', collider='box', scale=64, texture='grass', texture_scale=(4,4))
editor_camera = EditorCamera(enabled=False, ignore_paused=True)
player = FirstPersonController(model='cube', z=-10, color=color.orange, origin_y=-.5, speed=8)
player.collider = BoxCollider(player, Vec3(0,1,0), Vec3(1,2,1))
gun = Entity(model='cube', parent=camera, position=(.5,-.25,.25), scale=(.3,.2,1), origin_z=-.5, color=color.red, on_cooldown=False)
shootables_parent = Entity()
mouse.traverse_target = shootables_parent
for i in range(16):
Entity(model='cube', origin_y=-.5, scale=2, texture='brick', texture_scale=(1,2),
x=random.uniform(-8,8),
z=random.uniform(-8,8) + 8,
collider='box',
scale_y = random.uniform(2,3),
color=color.hsv(0, 0, random.uniform(.9, 1))
)
sun = DirectionalLight()
sun.look_at(Vec3(1,-1,-1))
Sky()
vr = VideoRecorder(duration=10)
def input(key):
if key == '5':
vr.start_recording()
if key == '6':
vr.stop_recording()
app.run()
Related
I have a question about using pyqt5 and pygame. I have already made a pygame script and a pyqt5 script. The problem is that when I want to make pygame excute the game, it shows a ranking board in pyqt5 and plays game by a pygame script.
This is my pyqt UI code:
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtGui import QMovie
import rankingUI
import sys
import main
import pickle
import subprocess
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.setFixedSize(800,400)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
# create label
self.label = QtWidgets.QLabel(self.centralwidget)
self.label.move(0,0)
# start button
self.button = QtWidgets.QPushButton(self.centralwidget)
self.button.setGeometry(320,300,150,100)
self.button.setStyleSheet("border-image:url(./assets/ui/start_btn.png); border:0px;")
self.button.clicked.connect(self.game_start)
# title
self.title = QtWidgets.QLabel(self.centralwidget)
self.title.setGeometry(250, 10, 300, 100)
self.title.setStyleSheet("border-image:url(./assets/ui/dinotitle.png); border:0px;")
# input nick
self.nick_inp = QtWidgets.QLineEdit("ENTER YOUR NICK",self.centralwidget)
self.nick_inp.setAlignment(QtCore.Qt.AlignCenter)
self.nick_inp.setGeometry(320,290, 150 ,20)
#ranking
self.ranking_btn = QtWidgets.QPushButton(self.centralwidget)
self.ranking_btn.setStyleSheet("border-image:url(./assets/ui/rank_btn.png); border:0px;")
self.ranking_btn.setGeometry(730, 325, 50, 50)
self.ranking_btn.clicked.connect(self.popup_ranking)
# add popup
self.add_dia = QtWidgets.QDialog()
self.rank_dia = QtWidgets.QDialog()
# add label to main window
MainWindow.setCentralWidget(self.centralwidget)
# set qmovie as label
self.movie = QMovie("assets/ui/dinogif.gif")
self.label.setMovie(self.movie)
self.movie.start()
def game_start(self):
player_nick = self.nick_inp.text()
if(len(player_nick)==0):
self.nick_inp.setText("ENTER YOUR NICK")
return
main.game_start(player_nick)
def popup_ranking(self):
# ui init
self.rank_dia.setWindowModality(QtCore.Qt.ApplicationModal)
self.rank_dia.setWindowTitle("RANKING")
self.rank_dia.setFixedSize(500,330)
rank_label = QtWidgets.QLabel("RANKKING")
rank_label.setAlignment(QtCore.Qt.AlignCenter)
rank_label.setFont(QtGui.QFont('Arial', 30))
output = QtWidgets.QTextEdit()
output.setFont(QtGui.QFont('Ubuntu',15))
window = QtWidgets.QVBoxLayout()
window.addWidget(rank_label)
window.addWidget(output)
# read data
rank_list = []
ranking_dat = open("ranking.dat", 'rb')
try:
rank_list = pickle.load(ranking_dat)
except:
pass
ranking_dat.close()
# write data
strFormat = '%-18s%-18s%-18s\n'
strOut = strFormat % ('RANK', 'SCORE', 'NICK')
rank_num = 1
strFormat = '%-20s%-20s%-20s\n'
for x in sorted(rank_list, key=lambda s: s["Score"], reverse=True):
tmp = []
tmp.append(str(rank_num))
rank_num += 1
for y in x:
tmp.append(str(x[y]))
strOut += strFormat % (tmp[0], tmp[2], tmp[1])
if rank_num == 10:
break
output.setText(strOut)
self.rank_dia.setLayout(window)
self.rank_dia.show()
# def score_reg(self):
# # popup UI setting
# self.add_dia.setWindowTitle("score registration")
# self.add_dia.setWindowModality(QtCore.Qt.ApplicationModal)
# self.add_dia.setFixedSize(300,70)
#
# # add widget
# nick_label = QtWidgets.QLabel("Insert Nickname :")
# self.nick_input = QtWidgets.QLineEdit()
# score_label = QtWidgets.QLabel("Your Score : ")
# self.score_input = QtWidgets.QLabel("333")
# reg_btn = QtWidgets.QPushButton("register")
# reg_btn.clicked.connect(self.register)
#
# h_box1 = QtWidgets.QHBoxLayout()
# h_box1.addWidget(nick_label)
# h_box1.addWidget(self.nick_input)
#
# h_box2 = QtWidgets.QHBoxLayout()
# h_box2.addWidget(score_label)
# h_box2.addWidget(self.score_input)
# h_box2.addStretch()
# h_box2.addWidget(reg_btn)
#
# v_box = QtWidgets.QVBoxLayout()
# v_box.addLayout(h_box1)
# v_box.addLayout(h_box2)
#
# self.add_dia.setLayout(v_box)
# self.add_dia.show()
#
# def register(self):
# print(self.nick_input.text())
# print(self.score_input.text())
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
window = QtWidgets.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(window)
window.show()
sys.exit(app.exec_())
This is the pygame code:
import pygame as pyg
import os
import random
import sys
import pickle
import pygame.time
import ui
nickname = ...
# 화면 크기
SCREEN_HEIGHT = 600
SCREEN_WIDTH = 1600
SCREEN = ...
# 달리는 모션 (running1, running2)
RUNNING_MOTIONS = [pyg.image.load(os.path.join("assets/Dino", "DinoRun1.png")),
pyg.image.load(os.path.join("assets/Dino", "DinoRun2.png"))]
# 뛰는 모션, 숙이는 모션 (stooping1, stooping2)
JUMPING_MOTION = pyg.image.load(os.path.join("assets/Dino", "DinoJump.png"))
STOOPING_MOTIONS = [pyg.image.load(os.path.join("assets/Dino", "DinoStoop1.png")),
pyg.image.load(os.path.join("assets/Dino", "DinoStoop2.png"))]
# 선인장
SMALL_CACTUS_IMG = [pyg.image.load(os.path.join("assets/Cactus", "SmallCactus1.png")),
pyg.image.load(os.path.join("assets/Cactus", "SmallCactus2.png")),
pyg.image.load(os.path.join("assets/Cactus", "SmallCactus3.png"))]
LARGE_CACTUS_IMG = [pyg.image.load(os.path.join("assets/Cactus", "LargeCactus1.png")),
pyg.image.load(os.path.join("assets/Cactus", "LargeCactus2.png")),
pyg.image.load(os.path.join("assets/Cactus", "LargeCactus3.png"))]
# 새 모션
BIRD_MOTIONS = [pyg.image.load(os.path.join("assets/Bird", "Bird1.png")),
pyg.image.load(os.path.join("assets/Bird", "Bird2.png"))]
# 기타 (구름, 바닥) -> 하트 추가 예정
CLOUD = pyg.image.load(os.path.join("assets/Other", "Cloud.png"))
GROUND = pyg.image.load(os.path.join("assets/Other", "Track.png"))
global points
class Dinosaur():
X_Dino = 80
Y_Dino = 310
Y_DinoStoop = 340
Jump_height = 8.5
hitScale = 0.5
def __init__(self):
self.stoop_img = STOOPING_MOTIONS
self.run_img = RUNNING_MOTIONS
self.jump_img = JUMPING_MOTION
self.dino_stoop = False
self.dino_run = True
self.dino_jump = False
self.step_index = 0 # 움직임 인덱스
self.jump_height = self.Jump_height
self.image = self.run_img[0] # 0, 1 인덱스 반복하여 애니메이션 구현
self.dino_hitbox = self.image.get_rect() # 공룡 히트박스 설정
self.dino_hitbox.x = self.X_Dino * self.hitScale
self.dino_hitbox.y = self.Y_Dino * self.hitScale
def update(self, Input):
if self.dino_stoop:
self.stoop()
if self.dino_run:
self.run()
if self.dino_jump:
self.jump()
if self.step_index >= 10:
self.step_index = 0
# 공룡 동작
# 점프
if Input[pyg.K_UP] and not self.dino_jump:
self.dino_stoop = False
self.dino_run = False
self.dino_jump = True
# 숙이기
elif Input[pyg.K_DOWN] and not self.dino_jump:
self.dino_stoop = True
self.dino_run = False
self.dino_jump = False
# 달리기
elif not (self.dino_jump or Input[pyg.K_DOWN]):
self.dino_stoop = False
self.dino_run = True
self.dino_jump = False
def stoop(self):
self.image = self.stoop_img[self.step_index // 5]
self.dino_hitbox = self.image.get_rect()
self.dino_hitbox.x = self.X_Dino
self.dino_hitbox.y = self.Y_DinoStoop
self.step_index += 1
def run(self):
self.image = self.run_img[self.step_index // 5] # 5로 해야 속도 맞음
self.dino_hitbox = self.image.get_rect()
self.dino_hitbox.x = self.X_Dino
self.dino_hitbox.y = self.Y_Dino
self.step_index += 1
def jump(self):
self.image = self.jump_img
if self.dino_jump:
self.dino_hitbox.y -= self.jump_height * 4
self.jump_height -= 0.8
if self.jump_height < - self.Jump_height:
self.dino_jump = False
self.jump_height = self.Jump_height
def draw(self, SCREEN):
SCREEN.blit(self.image, (self.dino_hitbox.x, self.dino_hitbox.y))
class Cloud():
def __init__(self):
self.x = SCREEN_WIDTH + random.randint(800, 1000)
self.y = random.randint(50, 100)
self.image = CLOUD
self.width = self.image.get_width()
def update(self):
self.x -= game_speed
if self.x < - self.width:
self.x = SCREEN_WIDTH + random.randint(2600, 3000)
self.y = random.randint(50, 100)
def draw(self, SCREEN):
SCREEN.blit(self.image, (self.x, self.y))
class Obstacle():
def __init__(self, image, type):
self.image = image
self.type = type
self.rect = self.image[self.type].get_rect()
self.rect.x = SCREEN_WIDTH
def update(self):
self.rect.x -= game_speed
if self.rect.x < - self.rect.width:
obstacles.pop()
def draw(self, SCREEN):
SCREEN.blit(self.image[self.type], self.rect)
class SmallCactus(Obstacle):
def __init__(self, image):
self.type = random.randint(0, 2)
super().__init__(image, self.type)
self.rect.y = 325
class LargeCactus(Obstacle):
def __init__(self, image):
self.type = random.randint(0, 2)
super().__init__(image, self.type)
self.rect.y = 300
class Bird(Obstacle):
def __init__(self, image):
self.type = 0
super().__init__(image, self.type)
self.rect.y = 250
self.index = 0
def draw(self, SCREEN):
if self.index >= 9:
self.index = 0
SCREEN.blit(self.image[self.index // 5], self.rect)
self.index += 1
def main():
global game_speed, x_ground, y_ground, points, obstacles
run = True
clock = pyg.time.Clock()
cloud = Cloud()
player = Dinosaur()
game_speed = 14
x_ground = 0
y_ground = 380
points = 0
font = pyg.font.Font('freesansbold.ttf', 20)
obstacles = []
death_cnt = 0
def score():
global points, game_speed
points += 1
if points % 100 == 0:
game_speed += 1
text = font.render("points: " + str(points), True, (0,0,0))
text_rect = text.get_rect()
text_rect.center = (1000, 40)
SCREEN.blit(text, text_rect)
def ground():
global x_ground, y_ground
image_width = GROUND.get_width()
SCREEN.blit(GROUND, (x_ground, y_ground))
SCREEN.blit(GROUND, (image_width + x_ground, y_ground))
if x_ground <= - image_width:
SCREEN.blit(GROUND, (image_width + x_ground, y_ground))
x_ground = 0
x_ground -= game_speed
while run:
for pyEvent in pyg.event.get():
if pyEvent.type == pyg.QUIT:
sys.exit()
SCREEN.fill((255,255,255))
userInput = pyg.key.get_pressed()
player.draw(SCREEN)
player.update(userInput)
if len(obstacles) == 0:
if random.randint(0, 2) == 0:
obstacles.append(SmallCactus(SMALL_CACTUS_IMG))
elif random.randint(0, 2) == 1:
obstacles.append(LargeCactus(LARGE_CACTUS_IMG))
elif random.randint(0, 2) == 2:
obstacles.append(Bird(BIRD_MOTIONS))
for ob in obstacles:
ob.draw(SCREEN)
ob.update()
if player.dino_hitbox.colliderect(ob.rect):
pyg.time.delay(500)
death_cnt += 1
menu(death_cnt)
ground()
cloud.draw(SCREEN)
cloud.update()
score()
clock.tick(30)
pyg.display.update()
def menu(death_cnt):
global points
run = True
if death_cnt == 0:
points = 0
while run:
update(points)
SCREEN.fill((255,255,255))
font = pyg.font.Font('freesansbold.ttf', 30) # 폰트 적용 오류......
if death_cnt == 0:
text = font.render("Press any key to Start", True, (0,0,0)) # 한글 "시작하기" 로 변경 예정
text1 = font.render("DinoSaurGame", True, (0,0,0)) # "공룡게임"으로 변경 예정
elif death_cnt > 0:
text = font.render("Press any key to Restart", True, (0,0,0))
score = font.render("Your Score : " + str(points), True, (0,0,0))
scoreRect = score.get_rect()
scoreRect.center = (SCREEN_WIDTH // 2, SCREEN_HEIGHT // 2 + 50)
SCREEN.blit(score, scoreRect)
textRect = text.get_rect()
textRect.center = (SCREEN_WIDTH // 2, SCREEN_HEIGHT // 2)
SCREEN.blit(text, textRect)
SCREEN.blit(RUNNING_MOTIONS[0], (SCREEN_WIDTH // 2 - 20, SCREEN_HEIGHT // 2 - 140))
pyg.display.update()
for pyEvent in pyg.event.get():
if pyEvent.type == pyg.QUIT:
sys.exit()
if pyEvent.type == pyg.KEYDOWN:
main()
def update(score):
pass
def game_start(nick):
pyg.init()
global SCREEN
global nickname
nickname = nick
SCREEN = pyg.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
menu(death_cnt=0)
When I quit the pygame window, pyqt5 quits too. How can I only quit the pygame window?
Do not mix frameworks, mixing frameworks always means some kind of undefined behavior. The frameworks may interact poorly or completely conflict with one another. Getting it to work on your system doesn't mean it will work on another system or with a different version of any of the frameworks.
If you use Qt, then I suggest to develop the game with Qt as well (see Qt Based Games).
This is my image rotaer, my problem is that the corners of the image are cut off. I also tried to change my label size, but it didn't work. Is there a way to make it bigger so the corners are no longer cut off or is there another way to solve the problem?
import sys
import os
import random
import numpy as np
import cv2
from PyQt5.QtWidgets import QApplication, QLabel, QGridLayout, QWidget, QPushButton
from PyQt5.QtGui import QPixmap, QTransform, QImage, QColor, qRgb
from PyQt5.QtCore import QTimer, pyqtSlot, Qt
class ImageRotater(QWidget):
isStoping = False
stepsLeft = -1
countAngle = 0
def __init__(self):
super().__init__()
self.bilder = []
self.getBilder()
rbild = random.choice(tuple(self.bilder))
self.item = cv2.imread(rbild,1)
self.item = cv2.flip(self.item, 1)
self.item = cv2.cvtColor(self.item, cv2.COLOR_BGR2RGB)
self.item = rotate_image(self.item, 90)
self.modi = rotate_image(self.item, 0)
im_np = np.array(self.modi)
im_np = np.transpose(im_np, (1, 0, 2)).copy()
self.im = QImage(im_np, im_np.shape[1], im_np.shape[0], QImage.Format_RGB888)
self.im = QPixmap(self.im)
self.transform = QTransform()
self.label = QLabel()
self.setStyleSheet("background-color: white;")
self.timer = QTimer()
self.angle = 0
self.Spbutton = QPushButton('Stop', self)
self.Spbutton.clicked.connect(self.stopButton)
self.Spbutton.setEnabled(False)
self.Spbutton.move(100, 70)
self.Sbutton = QPushButton('Start', self)
self.Sbutton.clicked.connect(self.startButton)
self.label.setPixmap(self.im)
self.label.setGeometry(0,0,1000,1000)
self.grid = QGridLayout()
self.grid.addWidget(self.label, 0, 0)
self.grid.addWidget(self.Sbutton,1,0)
self.grid.addWidget(self.Spbutton, 2, 0)
self.setLayout(self.grid)
self.timer.timeout.connect(self.transfromer)
self.setWindowTitle("Bild")
self.show()
#pyqtSlot()
def startButton(self):
self.Sbutton.setEnabled(False)
self.Spbutton.setEnabled(True)
self.timer.start(800)
self.isStoping = False
self.stepsLeft = -1
# self.countAngle = 0
def getBilder(self):
relevant_path = "./"
included_extensions = ['jpg', 'jpeg', 'bmp', 'png', 'gif', 'svg']
file_names = [fn for fn in os.listdir(relevant_path)
if any(fn.endswith(ext) for ext in included_extensions)]
self.bilder = file_names
def transfromer(self):
self.countAngle += 45
if self.countAngle == 360:
self.countAngle = 0
if self.isStoping == False:
self.modi = rotate_image(self.item, self.countAngle)
im_np = np.array(self.modi)
im_np = np.transpose(im_np, (1, 0, 2)).copy()
self.im = QPixmap(QImage(im_np, im_np.shape[1], im_np.shape[0], QImage.Format_RGB888))
self.label.setPixmap(self.im)
elif self.stepsLeft > 0:
self.modi = rotate_image(self.item, self.countAngle)
im_np = np.array(self.modi)
im_np = np.transpose(im_np, (1, 0, 2)).copy()
self.im = QPixmap(QImage(im_np, im_np.shape[1], im_np.shape[0], QImage.Format_RGB888))
self.label.setPixmap(self.im)
self.stepsLeft -= 1
else:
self.Sbutton.setEnabled(True)
self.countAngle -= 45
self.timer.stop()
def roll(self):
zufall = random.randint(0, 1)
if zufall == 0:
self.stepsLeft = ((360-self.countAngle) / 45)
return
if self.countAngle > 180:
self.stepsLeft = ((360 - self.countAngle) / 45)
self.stepsLeft += 4
else:
self.stepsLeft = ((180 - self.countAngle) / 45)
#pyqtSlot()
def stopButton(self):
self.isStoping = True
self.roll()
self.Spbutton.setEnabled(False)
if self.stepsLeft <= 2:
self.stepsLeft += 8
def rotate_image(image, angle):
image_center = tuple(np.array(image.shape[1::-1]) / 2)
rot_mat = cv2.getRotationMatrix2D(image_center, angle, 1.0)
result = cv2.warpAffine(image, rot_mat, image.shape[1::-1], flags=cv2.INTER_LINEAR)
return result
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = ImageRotater()
sys.exit(app.exec_())
This is the result when I start the rotation:
I have an GUI inventory and I don't know how to hide it and all the items there are inside. I tried to make the class Inventory(Entity) enabled or not and it didn't worked because it only gets enables and never disabled. This is my first post so, please, be nice.
My code:
from ursina import *
from ursina.prefabs.first_person_controller import FirstPersonController
app = Ursina()
class Inventory(Entity):
def __init__(self):
player.enabled = False
super().__init__(
parent = camera.ui,
model = 'quad',
scale = (.5, .8),
origin = (-.5, .5),
position = (-.3,.4),
texture = 'white_cube',
texture_scale = (5,8),
color = color.dark_gray
)
self.item_parent = Entity(parent=self, scale=(1/5,1/8))
enable = False
def input(key):
if key == 'f':
inventory_enable()
def inventory_enable():
inventory = Inventory()
Inventory().enable = False
...
Setting entity.enabled = False will deactivate it and all it's children. To make it reappear, set it back to True.
app = Ursina()
class Inventory(Entity):
def __init__(self):
player.enabled = False
super().__init__(
parent = camera.ui,
)
self.inventory_ui = Entity(parent = self,
model = 'quad',
scale = (.5, .8),
origin = (-.5, .5),
position = (-.3,.4),
texture = 'white_cube',
texture_scale = (5,8),
color = color.dark_gray,
enable = True
)
self.item_parent = Entity(parent=self.inventory_ui, scale=(1/5,1/8))
def find_free_spot(self):
taken_spots = [(int(e.x), int(e.y)) for e in self.item_parent.children]
for y in range(8):
for x in range(5):
if not (x,-y) in taken_spots:
return (x,-y)
def append(self, item):
icon = Draggable(
parent = Inventory().item_parent,
model = 'quad',
texture = item,
color = color.white,
origin = (-.5,.5),
position = self.find_free_spot(),
z = -.1,
)
name = item.replace('_', ' ').title()
icon.tooltip = Tooltip(name)
icon.tooltip.background.color = color.color(0,0,0,.8)
def drag():
icon.org_pos = (icon.x, icon.y)
def drop():
icon.x = int(icon.x)
icon.y = int(icon.y)
'''if the spot is taken, swap positions'''
for c in self.children:
if c == icon:
continue
if c.x == icon.x and c.y == icon.y:
print('swap positions')
c.position = icon.org_pos
icon.drag = drag
icon.drop = drop
#removed load_texture
grass_texture = "assets/grass.png"
soil_texture = "assets/soil.png"
stone_texture = "assets/stone.png"
wood_texture = "assets/wood.png"
sky_texture = load_texture("assets/skybox.png")
current_texture = grass_texture
def update():
global current_texture
if held_keys['1']: current_texture = grass_texture
if held_keys['2']: current_texture = soil_texture
if held_keys['3']: current_texture = stone_texture
if held_keys['4']: current_texture = wood_texture
# added
if held_keys['g']:
save_game()
if held_keys['left mouse'] or held_keys['right mouse']:
hand.active()
else:
hand.passive()
def input(key):
key_f = 0
if key == 'escape':
quit()
if key == 'f' and key_f == 0:
key_f = 1
inventory_enable()
else:
key_f = 0
inventory_close()
def inventory_close():
Inventory().inventory_ui.enable = False
def inventory_enable():
inventory = Inventory()
Inventory().enable = False
def add_item():
Inventory().append(random.choice(('bag', 'bow_arrow', 'gem', 'orb', 'sword')))
for i in range(7):
add_item()
add_item_button = Button(
scale = (.1,.1),
x = -.5,
color = color.lime.tint(-.25),
text = '+',
tooltip = Tooltip('Add random item'),
on_click = add_item
)
By setting gui.enable = False or gui.visible = False you can hide the gui. gui.enable = False disables it and all of his parents, gui.visible = False just makes it invisible.
My Kivy app shows on left bottom of screen of phone (You can see in shared screenshot).But I want to make it fullscreen.I make value of "fullscreen" equal to 1 in "buildozer.spec" file.But nothing changed.Here is my code:
from kivy.app import App
from kivy.core.window import Window
from kivy.uix.gridlayout import GridLayout
from kivy.uix.widget import Widget
from kivy.uix.image import Image
from kivy.clock import Clock
from kivy.uix.behaviors import ButtonBehavior
from kivy.core.audio import SoundLoader
Window.size = (320,640)
opart = False
vpart = False
rpart = False
och = False
vch = False
rch = False
ofin = False
vfin = False
rfin = False
fin = True
snd_part = SoundLoader.load("part.wav")
music = SoundLoader.load("music.wav")
music.play()
class Orange(ButtonBehavior,Image):
def __init__(self,**kwargs):
super(Orange,self).__init__(**kwargs)
self.source = "obal.png"
self.size = (85,113)
self.pos = (32,300)
def on_press(self):
global opart
opart = True
Clock.schedule_interval(self.todown,0.1)
def todown(self,*args):
global och
if not och:
snd_part.play()
self.source = "effect.png"
och = True
else:
self.x = 28
self.source = "esma.png"
if self.y > 250:
self.y -= 4
else:
self.y = 250
global ofin,fin
ofin = True
if vfin and rfin and fin:
fin = False
win.kill_platform()
class Violet(ButtonBehavior,Image):
def __init__(self,**kwargs):
super(Violet,self).__init__(**kwargs)
self.source = "vbal.png"
self.size = (85,113)
self.pos = (117,364)
def on_press(self):
global vpart
vpart = True
Clock.schedule_interval(self.todown,0.1)
def todown(self,*args):
global vch
if not vch:
snd_part.play()
self.source = "effect.png"
vch = True
else:
self.x = 113
self.source = "yaxsiki.png"
if self.y > 250:
self.y -= 4
else:
self.y = 250
global vfin,fin
vfin = True
if ofin and rfin and fin:
fin = False
win.kill_platform()
class Red(ButtonBehavior,Image):
def __init__(self,**kwargs):
super(Red,self).__init__(**kwargs)
self.source = "rbal.png"
self.size = (85,113)
self.pos = (202,300)
def on_press(self):
global rpart
rpart = True
Clock.schedule_interval(self.todown,0.1)
def todown(self,*args):
global rch
if not rch:
snd_part.play()
self.source = "effect.png"
rch = True
else:
self.x = 198
self.source = "varsan.png"
if self.y > 250:
self.y -= 4
else:
self.y = 250
global rfin,fin
rfin = True
if ofin and vfin and fin:
fin = False
win.kill_platform()
class Platform(Widget):
def __init__(self,**kwargs):
super(Platform,self).__init__(**kwargs)
self.size = (320,640)
self.bgimage = Image(source = "bg.jpg")
self.bgimage.size = (320,640)
self.obeta = False
self.vbeta = False
self.rbeta = False
self.obal = Orange()
self.vbal = Violet()
self.rbal = Red()
Clock.schedule_interval(self.moveOrange,0.1)
Clock.schedule_interval(self.moveViolet,0.1)
Clock.schedule_interval(self.moveRed,0.1)
self.bgimage.add_widget(self.obal)
self.bgimage.add_widget(self.vbal)
self.bgimage.add_widget(self.rbal)
self.add_widget(self.bgimage)
def moveOrange(self,*args):
if not opart:
if not self.obeta:
self.obal.y += 2
else:
self.obal.y -= 2
if self.obal.y <= 280:
self.obeta = False
if self.obal.y >= 320:
self.obeta = True
def moveViolet(self,*args):
if not vpart:
if not self.vbeta:
self.vbal.y += 1
else:
self.vbal.y -= 1
if self.vbal.y <= 344:
self.vbeta = False
if self.vbal.y >= 384:
self.vbeta = True
def moveRed(self,*args):
if not rpart:
if not self.rbeta:
self.rbal.y += 3
else:
self.rbal.y -= 3
if self.rbal.y <= 280:
self.rbeta = False
if self.rbal.y >= 320:
self.rbeta = True
class Platform2(Widget):
def __init__(self,**kwargs):
super(Platform2,self).__init__(**kwargs)
self.size = (320,640)
self.bgimage = Image(source = "bg.jpg")
self.bgimage.size = (320,640)
self.add_widget(self.bgimage)
class MainApp(App):
def build(self):
self.layout = GridLayout()
self.platform = Platform()
self.layout.add_widget(self.platform)
return self.layout
def kill_platform(self):
self.platform = Platform2()
self.layout.add_widget(self.platform)
win = MainApp()
win.run()
Here you can see screenshot.That's how it shows on my phone:
enter image description here
Replace the Window.size = (320,640) line with:
from kivy.utils import platform
if platform not in ["android", "ios"]:
Window.size = (320,640)
Side notes, you might wanna change the attributes that use the 320x640 pixel count or at least smaller than it to something like size_hint=(1,1). This answer might be unclear for most, but this is the best I can do
I'm writing a code that I would like to repeat automatically, and for the most part I have it. If I use a while loop I can get it to repeat, but I have to close the window automatically for it to work. Is there any way I can get it to close by itself?
The program is a slideshow.
Code wise, the loop I'm using looks like this:
while True:
execfile("slideshowtest.py")
If you need the rest of the code it looks like this:
import os
import pygtk
pygtk.require('2.0')
import gtk
import glib
def is_image(filename):
if not os.path.isfile(filename):
return False
for suffix in ['.jpg', '.png', '.bmp']:
if filename.lower().endswith(suffix):
return True
return False
def resizeToFit(image, frame, aspect=True, enlarge=False):
if aspect:
return scaleToFit(image, frame, enlarge)
else:
return stretchToFit(image, frame, enlarge)
def scaleToFit(image, frame, enlarge=False):
image_width, image_height = image
frame_width, frame_height = frame
image_aspect = float(image_width) / image_height
frame_aspect = float(frame_width) / frame_height
if not enlarge:
max_width = min(frame_width, image_width)
max_height = min(frame_height, image_height)
else:
max_width = frame_width
max_height = frame_height
if frame_aspect > image_aspect:
height = max_height
width = int(height * image_aspect)
else:
width = max_width
height = int(width / image_aspect)
return (width, height)
def stretchToFit(image, frame, enlarge=False):
image_width, image_height = image
frame_width, frame_height = frame
if not enlarge:
width = min(frame_width, image_width)
height = min(frame_height, image_height)
else:
width = frame_width
height = frame_height
return (width, height)
class ResizableImage(gtk.DrawingArea):
def __init__(self, aspect=True, enlarge=False,
interp=gtk.gdk.INTERP_NEAREST, backcolor=None, max=(1600,1200)):
super(ResizableImage, self).__init__()
self.pixbuf = None
self.aspect = aspect
self.enlarge = enlarge
self.interp = interp
self.backcolor = backcolor
self.max = max
self.connect('expose_event', self.expose)
self.connect('realize', self.on_realize)
def on_realize(self, widget):
if self.backcolor is None:
color = gtk.gdk.Color()
else:
color = gtk.gdk.Color(*self.backcolor)
self.window.set_background(color)
def expose(self, widget, event):
self.context = self.window.cairo_create()
self.context.rectangle(
event.area.x, event.area.y,
event.area.width, event.area.height)
self.context.clip()
self.draw(self.context)
return False
def draw(self, context):
rect = self.get_allocation()
x, y = rect.x, rect.y
parent = self.get_parent()
if parent:
offset = parent.get_allocation()
x -= offset.x
y -= offset.y
if self.backcolor:
context.rectangle(x, y, rect.width, rect.height)
context.set_source_rgb(*self.backcolor)
context.fill_preserve()
if not self.pixbuf:
return
width, height = resizeToFit(
(self.pixbuf.get_width(), self.pixbuf.get_height()),
(rect.width, rect.height),
self.aspect,
self.enlarge)
x = x + (rect.width - width) / 2
y = y + (rect.height - height) / 2
context.set_source_pixbuf(
self.pixbuf.scale_simple(width, height, self.interp), x, y)
context.paint()
def set_from_pixbuf(self, pixbuf):
width, height = pixbuf.get_width(), pixbuf.get_height()
if not self.max or (width < self.max[0] and height < self.max[1]):
self.pixbuf = pixbuf
else:
width, height = resizeToFit((width, height), self.max)
self.pixbuf = pixbuf.scale_simple(
width, height,
gtk.gdk.INTERP_BILINEAR)
self.invalidate()
def set_from_file(self, filename):
self.set_from_pixbuf(gtk.gdk.pixbuf_new_from_file(filename))
def invalidate(self):
self.queue_draw()
class DemoGtk:
SECONDS_BETWEEN_PICTURES = 2
FULLSCREEN = True
WALK_INSTEAD_LISTDIR = True
def __init__(self):
self.window = gtk.Window()
self.window.connect('destroy', gtk.main_quit)
self.window.set_title('Slideshow')
self.image = ResizableImage( True, True, gtk.gdk.INTERP_BILINEAR)
self.image.show()
self.window.add(self.image)
self.load_file_list()
self.window.show_all()
if self.FULLSCREEN:
self.window.fullscreen()
glib.timeout_add_seconds(self.SECONDS_BETWEEN_PICTURES, self.on_tick)
self.display()
def load_file_list(self):
self.files = []
self.index = 0
if self.WALK_INSTEAD_LISTDIR:
for directory, sub_directories, files in os.walk('.'):
for filename in files:
if is_image(filename):
filepath = os.path.join(directory, filename)
self.files.append(filepath)
else:
for filename in os.listdir('.'):
if is_image(filename):
self.files.append(filename)
print "Images:", self.files
def display(self):
if 0 <= self.index < len(self.files):
self.image.set_from_file(self.files[self.index])
return True
else:
return False
def on_tick(self):
self.index += 1
return self.display()
if __name__ == "__main__":
gui = DemoGtk()
gtk.main()
while True:
execfile("slideshowtest.py")
gtk Functions:
The gtk.main() function runs the main loop until the gtk.main_quit() function is called.
So you need to run your while loop in a separate thread and call main_quit() when you're finished.
Extending Ivan's answer, I needed window to close automatically after a couple of seconds. I ended up with something similar.
import threading
import time
def thread_function(name):
time.sleep(DISPLAY_TIME)
Gtk.main_quit()
x = threading.Thread(target=thread_function, args=(1,))
x.start() # Start thread and let thread sleep for N seconds
Gtk.main() # Start main Gtk
x.join()