Python Ursina hide UI - python

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.

Related

Entity Gravity ursina

I was starting to make a 3d game when i created a way to pick up certain entity's as boxes and move them around with the player. When i drop them however, they stay floating where they were. How to i add gravity to the entity? like when i drop the box, the box will fall with like with dynamic physics like in unity.
Here's my Code:
import ursina.application
from ursina import *
from ursina.prefabs.first_person_controller import FirstPersonController
app = Ursina()
window.fullscreen = True
window.fps_counter.enabled = False
window.color = color.black
window.exit_button.enabled = False
#===========================================
#from Player import _Player_
from Map import *
#==============================
player = FirstPersonController()
player.jump_up_duration = 1
player.jump_height = 5
player.gravity = 0.8
player.speed = 15
player.cursor.color = color.blue
player.y = 10
player.cursor.model = 'circle'
#===================movables
pbox = Entity(model = 'cube', scale = 1, position = (5, 1, 5), collider = 'box', name = 'box1')
pbox.add_script()
global pbox_hold
pbox_hold = False
#===============================
def exit_game():
app.userExit()
def show_game_menu():
Exit.enabled = True
game_menu_bd.enabled = True
def hide_game_menu():
Exit.enabled = False
game_menu_bd.enabled = False
def pause_handler_input(key):
if key == 'left mouse down' and mouse.hovered_entity == back_game:
back_game.enabled = False
hide_game_menu()
application.paused = not application.paused
mouse.locked = True
if key == 'left mouse down' and mouse.hovered_entity == Exit:
exit_game()
game_menu_bd = Button(scale = 10)
game_menu_bd.z = 0.1
game_menu_bd.enabled = False
back_game = Button(scale = (0.15, 0.07), position = (0, 0), ignore_paused = True, color = color.azure, text = 'Resume')
back_game.input = pause_handler_input
back_game.enabled = False
Exit = Button(model = 'quad' , scale = (0.05, 0.035), position = (window.exit_button.x-0.025, window.exit_button.y-0.015), color = color.red, ignore_paused = True, text = 'exit')
Exit.input = pause_handler_input
Exit.enabled = False
global holding_box_E
holding_box_E = pbox
#===================
def input(key):
global pbox_hold, holding_box_E
if key == "c":
mouse.locked = True
if key == "escape" or key == "x":
show_game_menu()
mouse.locked = False
back_game.enabled = True
ursina.application.paused = True
if key == 'left mouse down' and pbox_hold == False:
cast = raycast(player.position+Vec3(0, 1.9, 0), direction=(player.camera_pivot.forward), distance=4, traverse_target=pbox, debug=True)
#print(cast.hit)
if cast.hit:
pbox.color = color.blue
pbox_hold = True
holding_box_E = cast.entity
elif key == 'left mouse up' and pbox_hold == True:
pbox_hold = False
def update():
global pbox_hold, holding_box_E
if player.y < -20:
player.position = (0, 2, 0)
if pbox_hold == True:
holding_box_E.position = player.position + Vec3(0, 1.5, 0) + player.camera_pivot.forward + Vec3(player.camera_pivot.forward.x, player.camera_pivot.forward.y, player.camera_pivot.forward.z)*2
app.run()
NOTE that I have the map on a different script!!!
I just found a great library for ursina for implementing physics into entities.
Bullet-for-Ursina
the package lets you implement gravity into the scene/world to give objects dynamic physics with bounciness as well.
I would recommend since its easy to put in with you game.

ursina: how to save rendered frames as image or video?

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()

Time lag during a chess game in pyqt5 python

I've been designing a GUI-based chess game in PyQt5 (Python) . Since it is incomplete , there are some issues . But the biggest issue is , that after every move , the time lag in the GUI increases . After a particular time (say , move 8) , the GUI would almost stop working . Please help . The code is given below :
import PyQt5
from PyQt5 import QtWidgets
from PyQt5 import QtCore
from PyQt5 import QtGui
from PyQt5 import uic
import chess
import sys
import tabulate
class Chess_App(QtWidgets.QMainWindow):
def __init__(self):
super(Chess_App, self).__init__()
uic.loadUi("CHESS.ui", self)
self.move_name = ""
self.move = ""
self.board_rows = [8,7,6,5,4,3,2,1]
self.board_columns = 'a b c d e f g h'.split(" ")
# variable_needed = f"{self.board_columns[7-(n//8)]}{self.board_rows[n%8]}"
font = QtGui.QFont()
font.setPointSize(1)
self.win = None
self.draw = None
self.valid_move = True
self.Chess_Board = {n:QtWidgets.QPushButton(self) for n in range(64)}
for i in range(64):
self.Chess_Board[i].setStyleSheet("QPushButton {background-color : lightgreen ; color : lightgreen}")
self.Chess_Board[i].setFont(font)
self.Chess_Board[i].setObjectName(f"{self.board_columns[i%8]}{self.board_rows[i//8]}")
self.lineEdit_2.setDisabled(True)
for i in range(64):
if (i // 8) % 2 == 0:
if i % 2 == 0:
self.Chess_Board[i].setStyleSheet("QPushButton {background-color : white}")
if (i // 8) % 2 == 1:
if i % 2 == 1:
self.Chess_Board[i].setStyleSheet("QPushButton {background-color : white}")
self.Chess_Board[i].setGeometry(60+((i%8)*50),140+((i//8)*50),50,50)
self.Chess_Board[i].clicked.connect(self.initiate_move)
self.lineEdit.isReadOnly()
self.pushButton_A.clicked.connect(self.play_move)
self.pushButton_B.clicked.connect(self.resignation)
self.pushButton_C.clicked.connect(self.draw_game)
self.pushButton_D.clicked.connect(self.save_game)
self.pushButton_E.clicked.connect(self.reset_game)
self.board = chess.Board()
self.chessboard()
self.show_board()
self.show()
def chessboard(self):
self.pgn = self.board.epd()
self.final_list = []
self.printable_list = []
pieces = self.pgn.split(" ", 1)[0]
rows = pieces.split("/")
for row in rows:
self.initial_list = []
for chessmen in row:
if chessmen.isdigit():
for i in range(0, int(chessmen)):
self.initial_list.append(".")
else:
self.initial_list.append(chessmen)
self.final_list.append(self.initial_list)
def initiate_move(self):
for i in range(64):
self.Chess_Board[i].setStyleSheet("QPushButton {background-color : lightgreen ; color : lightgreen}")
if (i // 8) % 2 == 0:
if i % 2 == 0:
self.Chess_Board[i].setStyleSheet("QPushButton {background-color : white}")
if (i // 8) % 2 == 1:
if i % 2 == 1:
self.Chess_Board[i].setStyleSheet("QPushButton {background-color : white}")
self.value = self.sender()
self.move = self.value.text().upper()
if self.move == "":
pass
elif len(self.move) == 1:
if self.move == "P":
pass
else:
self.move_name += self.move
self.value.setStyleSheet("QPushButton {background-color : cyan}")
for i in range(64):
self.Chess_Board[i].clicked.connect(self.play_move)
def play_move(self):
self.textBrowser.setText("")
self.valid_move = True
self.button = self.sender()
if len(self.button.text()) == 1:
self.move_name += f"x{self.button.objectName()}"
if self.button.text() == "":
self.move_name += self.button.objectName()
# if self.lineEdit.isEnabled():
# self.move = self.lineEdit.text()
# elif self.lineEdit_2.isEnabled():
# self.move = self.lineEdit_2.text()
try:
self.board.push_san(self.move_name)
except Exception as ex:
self.textBrowser.setText(f"{ex}")
self.valid_move = False
if self.valid_move == True:
if self.lineEdit.isEnabled():
self.lineEdit.setDisabled(True)
self.lineEdit_2.setDisabled(False)
else:
self.lineEdit.setDisabled(False)
self.lineEdit_2.setDisabled(True)
elif self.valid_move == False:
self.move_name = ""
if self.board.is_checkmate():
self.textBrowser.setText("Checkmate !")
self.win = True
self.end_the_game()
if self.board.is_variant_draw():
self.textBrowser.setText("Draw !")
self.draw = True
self.end_the_game()
if self.board.is_stalemate():
self.textBrowser.setText("Stalemate !")
self.draw = True
self.end_the_game()
if self.board.is_fifty_moves():
self.textBrowser.setText("Draw by fifty-move rule !")
self.draw = True
self.end_the_game()
if self.board.is_repetition():
self.textBrowser.setText("Draw by three-fold repitition !")
self.draw = True
self.end_the_game()
self.chessboard()
self.show_board()
for i in range(64):
self.Chess_Board[i].clicked.connect(self.initiate_move)
self.move = ""
self.move_name = ""
def show_board(self):
for x in range(8):
for y in range(8):
if self.final_list[x][y].isupper():
self.Chess_Board[x*8+y].setText(f"{self.final_list[x][y]}".upper())
self.Chess_Board[x*8+y].setIcon(QtGui.QIcon(f"{self.final_list[x][y]}#.png"))
self.Chess_Board[x*8+y].setIconSize(QtCore.QSize(40,40))
elif self.final_list[x][y].islower():
self.Chess_Board[x*8+y].setText(f"{self.final_list[x][y]}".lower())
self.Chess_Board[x*8+y].setIcon(QtGui.QIcon(f"{self.final_list[x][y]}&.png"))
self.Chess_Board[x*8+y].setIconSize(QtCore.QSize(40,40))
elif self.final_list[x][y] == ".":
self.Chess_Board[x*8+y].setIcon(QtGui.QIcon())
self.Chess_Board[x*8+y].setText("")
def reset_game(self):
self.board.reset()
self.lineEdit.setText("")
self.lineEdit_2.setText("")
self.lineEdit.setDisabled(False)
self.lineEdit_2.setDisabled(True)
self.textBrowser.setText("")
self.chessboard()
self.show_board()
self.end_the_game()
def draw_game(self):
self.draw = True
self.end_the_game()
self.textBrowser.setText("It's a draw .")
def resignation(self):
if self.lineEdit.text() == self.lineEdit_2.text() == "":
self.textBrowser.setText("Match Aborted")
else:
if self.move == self.lineEdit.text():
self.win = True
self.end_the_game()
who_resigned = "Black"
elif self.move == self.lineEdit_2.text():
self.win = False
self.end_the_game()
who_resigned = "White"
self.textBrowser.setText(f"{who_resigned} resigned")
def save_game(self):
self.chesstable = tabulate.tabulate(self.final_list, tablefmt="grid", stralign="left")
with open("chess_save_list.txt","a") as writer:
writer.write(self.chesstable)
def end_the_game(self):
if self.win != self.draw:
self.pushButton_A.setDisabled(True)
self.pushButton_B.setDisabled(True)
self.pushButton_C.setDisabled(True)
self.win, self.draw = None, None
elif self.win == self.draw:
self.pushButton_A.setDisabled(False)
self.pushButton_B.setDisabled(False)
self.pushButton_C.setDisabled(False)
app = QtWidgets.QApplication(sys.argv)
window = Chess_App()
app.exec_()
The link to get the .ui link for the code : https://github.com/Vishal01-VKP/Python-Projects/blob/master/GUIs/Games/Chess%20-%20By%20VK/CHESS.ui
Thank you .
It is lagging over time because after each and every move you are connecting the clicked signal again for all 64 buttons in play_move and initiate_move.. connected signal's slot function will be executed in event loop, causing the lag in game
if you are connecting the signal again doesn't mean it will disconnect previous signal but rather add other signals, so after one or two moves each move will cause the 64 signals to connect again, after 5 to 6 moves it will have more than 5000 slots connected to each signal..
If the signal is connected to slot, it will remain connected until it is destroyed or explicitly disconnected..
So Modify your code accordingly so signals doesn't have to be connected again or Disconnect the signals before connecting them again(It could work but not recommended)

How to pass pixbuf from a class in a module,after user interaction, in Python

Im working on a python module to handle screenshots. The module itself works fine if alone. however when i import it into my main project i cant figure out how to return a pixbuf after waiting for the user to select a region to capture.
here is the screenshot module:
class CaptureRegion():
def __init__(self):
self.ThePic = None
self.drawArea = Gtk.DrawingArea()
self.drawArea.connect('draw',self.onDraw)
mBox = Gtk.VBox(False,2)
mBox.pack_start(self.drawArea,True,True,2)
self.MaskWin = Gtk.Window()
self.MaskWin.set_position(Gtk.WindowPosition.CENTER)
self.MaskWin.connect("key-press-event", self.KeyPress)
self.MaskWin.connect("button-press-event", self.ButtonPress)
self.MaskWin.connect("button-release-event", self.ButtonRelease)
self.MaskWin.connect("motion-notify-event", self.Motion)
self.MaskWin.add(mBox)
self.button_x = 0
self.button_y = 0
self.button_down = False
self.sel_rect = Gdk.Rectangle(-10, -10, 10, 10)
self.capfull = CaptureScreen()
self.fullpixbuf = self.capfull.Go()
def onDraw(self, widget, event):
print("Draw")
myGdkWindow = self.MaskWin.get_window()
self.cr = Gdk.cairo_create(myGdkWindow)
self.cr.set_operator(cairo.OPERATOR_SOURCE)
self.cr.set_source_rgb(1,1,1)
Gdk.cairo_set_source_pixbuf(self.cr, self.fullpixbuf, 5, 5)
self.cr.paint()
self.cr.set_line_width(1)
self.cr.set_source_rgb(0,0,0)
if self.button_down == True:
x = self.sel_rect.x
y = self.sel_rect.y
w = self.sel_rect.width
h = self.sel_rect.height
if w <= 0 or h <= 0:
return True
self.cr.rectangle(x,y,w,h)
self.cr.set_source_rgba(0.2, 0.6, 0.8, 0.35)
self.cr.set_line_width(2)
self.cr.stroke()
return True
def Motion(self,widget,event):
if self.button_down == False:
return False
x1,y1 = self.button_x, self.button_y
x2,y2 = event.x, event.y
x = int(min(x1,x2))
y = int(min(y1,y2))
w = int(abs(x1-x2))
h = int(abs(y1-y2))
old = self.sel_rect
self.sel_rect.x = x
self.sel_rect.y = y
self.sel_rect.width = w
self.sel_rect.height = h
win = self.MaskWin.get_window()
sx, sy, sw, sh = self.MaskWin.get_window().get_geometry()
self.drawArea.queue_draw_area(sx,sy,sw,sh)
def ButtonPress(self,widget,event):
if not event.button == 1:
return False
print("button down")
self.debounce = 0
self.button_x, self.button_y = event.x, event.y
self.button_down = True
return True
def ButtonRelease(self,widget,event):
self.button_down = False
x = self.sel_rect.x
y = self.sel_rect.y
w = self.sel_rect.width
h = self.sel_rect.height
self.drawArea.queue_draw_area(x-1, y-1, w-1, h-1)
if self.debounce == 0:
self.debounce += 1
print("Snipping x:%s y:%s w:%s h:%s" %(x,y,w,h))
self.ThePic = Gdk.pixbuf_get_from_window(self.MaskWin.get_window(), x, y, w, h)
self.MaskWin.hide()
#option 2: to return ThePic here after the selection is made thru a callback to a function in the main class
# i.e.
#self.CallbackInMain(self.ThePic) (not sure how to callback to the main class, self is wrong maybe?)
def KeyPress(self,widget,event):
if event.keyval == Gdk.KEY_Escape:
self.ThePic = None
return
def WaitThread(self):
for i in range(1, 50):
time.sleep(0.1)
print(i)
self.done_waiting.set()
def Go(self):
self.MaskWin.fullscreen()
self.MaskWin.show_all()
self.MaskWin.set_decorated(False)
#option 1 find a way to wait for the selection to complete like this:
#(this code doesnt end, the self.done_waiting.set() call doesnt stop it)
# self.done_waiting = threading.Event()
# self.thread = threading.Thread(target=self.WaitThread)
# self.thread.start()
# self.done_waiting.wait(1)
# print("Main thread is done waiting")
return(self.ThePic)
class CaptureScreen():
def __init__(self):
self.ThePic = None
def Go(self):
screen = Gdk.get_default_root_window()
x, y, width, height = screen.get_geometry()
self.fullpixbuf = Gdk.pixbuf_get_from_window(screen, x, y, width, height)
return(self.fullpixbuf)
im calling the class like this:
import Screentshot as Shot
self.captureregion = Shot.CaptureRegion()
pic = self.captureregion.Go()
pic.savev("region.png",'png',(),())
with the CaptureScreen class im just capturing the whole screen so i can return the pixbuf directly from the CaptureScreen.Go() function. however with the CaptureRegion class i have to wait for the user to select an area, and im not sure how to have CaptureRegion.Go() return the pixbuf after the users selection. I have two ideas, one use threading to wait for the selection to complete and then return the pixbuf from Capture Region.Go() (option 1 in code) , or second somehow have the screenshot class callback to function in main with the pixbuf as an arg(option 2 in code)
Im not very familiar with classes nor have i ever used the threading module. ive searched and found lots of info, i just cant quite wrap my head around what i need to do.
Of course now that i finally post a question about this, i figured it out. i just needed to add a second arg to Go(self,mainself) and call back to a function in the main code.
this is what i changed:
def ButtonRelease(self,widget,event):
self.button_down = False
x = self.sel_rect.x
y = self.sel_rect.y
w = self.sel_rect.width
h = self.sel_rect.height
self.drawArea.queue_draw_area(x-1, y-1, w-1, h-1)
if self.debounce == 0:
self.debounce += 1
print("Snipping x:%s y:%s w:%s h:%s" %(x,y,w,h))
self.ThePic = Gdk.pixbuf_get_from_window(self.MaskWin.get_window(), x, y, w, h)
self.MaskWin.hide()
self.GotTheShot = True
self.mainself.ScreenShotCallBack(self.ThePic)
def Go(self,main):
self.mainself = main
self.GotTheShot = False
self.MaskWin.fullscreen()
self.MaskWin.show_all()
self.MaskWin.set_decorated(False)
and here is the call and callback:
def ScreenShotRegion(self):
pic = self.captureregion.Go(self)# self,mainself... self passed by default
pic.savev("region.png",'png',(),())
def ScreenShotCallBack(self,capturepixbuf):
self.window.show_all()
capturepixbuf.savev("region.png",'png',(),())

Grid Generation for minesweeper

Hi so I am making a minesweeper game and I am a bit stuck with the grid generation part. This is my code so far:
from random import randint
import pygame
def MineGen():
mineamount = 100
grid_across = 40
grid_up = 25
mine_list = []
my2dthatlist = []
numacoss = 0
for i in range (mineamount):
numacoss = randint(1,40)
my2dthatlist.append(numacoss)
numup = randint(1,25)
my2dthatlist.append(numup)
mine_list.append(my2dthatlist)
my2dthatlist = []
return mine_list
def GridGen():
grid_across = 40
grid_up = 25
GRIDD = [[0]* grid_across for i in range(grid_up)]
return GRIDD
def MineGrid(GridOutMine, mine_list):
mineplace = 0
placeX = 0
placeY = 0
for i in range(100):
mineplace = mine_list[i]
placeX = mineplace[0]
placeY = mineplace[1]
GridOutMine[placeX][placeY] = 1
print(GridOutMine)
mine_list = MineGen()
GridOutMine = GridGen()
MineGrid(GridOutMine, mine_list)
My issue is that i am getting a list index out of range for the
GridOutMine[placeX][placeY] = 1
part. I don't really know why this is. If you could give me some assistance in what to do, or just some general comments on my code, I would really appreciate it thanks.
That's because, unlike range, random.randint outputs numbers within the specified bounds inclusively. That is, randint(1, 25) could output 25, which is not a valid index for a list that's only 25 elements long (since the last index is 24).
In MineGen, you need to change randint(1, 25) to randint(1, 25-1) or randint(1, 24), and likewise for randint(1, 40) which needs to be randint(1, 39). I'd actually suggest randint(0, 24) and (0, 39), but I don't know if that's intentional.
There are many other things that could/should be improved about this code, but I'd suggest you ask for that kind of input over on CodeReview instead of here once your code is working (they don't fix broken code).
EDIT:
Also, you're indexing your grid in the wrong order. It's a list (25-long) of rows (40-long), so you need to index it in the Y dimension first, then X: GridOutMine[placeY][placeX] = 1
If you are trying to build a grid for the game and want to display buttons in a GUI your users can interact with, you may want to start with the following code as a basic framework for the rest of the code you will be writing.
import tkinter
import functools
class MineSweep(tkinter.Frame):
#classmethod
def main(cls, width, height):
root = tkinter.Tk()
window = cls(root, width, height)
root.mainloop()
def __init__(self, master, width, height):
super().__init__(master)
self.__width = width
self.__height = height
self.__build_buttons()
self.grid()
def __build_buttons(self):
self.__buttons = []
for y in range(self.__height):
row = []
for x in range(self.__width):
button = tkinter.Button(self)
button.grid(column=x, row=y)
button['text'] = '?'
command = functools.partial(self.__push, x, y)
button['command'] = command
row.append(button)
self.__buttons.append(row)
def __push(self, x, y):
print('Column = {}\nRow = {}'.format(x, y))
if __name__ == '__main__':
MineSweep.main(10, 10)
If you want a more complete example of a minesweeper game to either borrow ideas from or adapt for your own needs, the following program implements much of the functionality you might want from a finished game.
import tkinter
import functools
import random
from tkinter.simpledialog import askstring, Dialog
from tkinter.messagebox import showinfo
import os.path
################################################################################
class MineSweep(tkinter.Frame):
#classmethod
def main(cls, width, height, mines, scores):
root = tkinter.Tk()
root.resizable(False, False)
root.title('MineSweep')
window = cls(root, width, height, mines, scores)
root.protocol('WM_DELETE_WINDOW', window.close)
root.mainloop()
################################################################################
def __init__(self, master, width, height, mines, scores):
super().__init__(master)
self.__width = width
self.__height = height
self.__mines = mines
self.__wondering = width * height
self.__started = False
self.__playing = True
self.__scores = ScoreTable()
self.__record_file = scores
if os.path.isfile(scores):
self.__scores.load(scores)
self.__build_timer()
self.__build_buttons()
self.grid()
def close(self):
self.__scores.save(self.__record_file)
self.quit()
def __build_timer(self):
self.__secs = tkinter.IntVar()
self.__timer = tkinter.Label(textvariable=self.__secs)
self.__timer.grid(columnspan=self.__width, sticky=tkinter.EW)
self.__after_handle = None
def __build_buttons(self):
self.__reset_button = tkinter.Button(self)
self.__reset_button['text'] = 'Reset'
self.__reset_button['command'] = self.__reset
self.__reset_button.grid(column=0, row=1,
columnspan=self.__width, sticky=tkinter.EW)
self.__reset_button.blink_handle = None
self.__buttons = []
for y in range(self.__height):
row = []
for x in range(self.__width):
button = tkinter.Button(self, width=2, height=1,
text='?', fg='red')
button.grid(column=x, row=y+2)
command = functools.partial(self.__push, x, y)
button['command'] = command
row.append(button)
self.__buttons.append(row)
def __reset(self):
for row in self.__buttons:
for button in row:
button.config(text='?', fg='red')
self.__started = False
self.__playing = True
self.__wondering = self.__width * self.__height
if self.__after_handle is not None:
self.after_cancel(self.__after_handle)
self.__after_handle = None
self.__secs.set(0)
def __push(self, x, y, real=True):
button = self.__buttons[y][x]
if self.__playing:
if not self.__started:
self.__build_mines()
while self.__buttons[y][x].mine:
self.__build_mines()
self.__started = True
self.__after_handle = self.after(1000, self.__tick)
if not button.pushed:
self.__push_button(button, x, y)
elif real:
self.__blink(button, button['bg'], 'red')
elif real:
self.__blink(button, button['bg'], 'red')
def __blink(self, button, from_bg, to_bg, times=8):
if button.blink_handle is not None and times == 8:
return
button['bg'] = (to_bg, from_bg)[times & 1]
times -= 1
if times:
blinker = functools.partial(self.__blink, button,
from_bg, to_bg, times)
button.blink_handle = self.after(250, blinker)
else:
button.blink_handle = None
def __tick(self):
self.__after_handle = self.after(1000, self.__tick)
self.__secs.set(self.__secs.get() + 1)
def __push_button(self, button, x, y):
button.pushed = True
if button.mine:
button['text'] = 'X'
self.__playing = False
self.after_cancel(self.__after_handle)
self.__after_handle = None
self.__blink(self.__reset_button, button['bg'], 'red')
else:
button['fg'] = 'SystemButtonText'
count = self.__total(x, y)
button['text'] = count and str(count) or ' '
self.__wondering -= 1
if self.__wondering == self.__mines:
self.after_cancel(self.__after_handle)
self.__after_handle = None
self.__finish_game()
def __finish_game(self):
self.__playing = False
score = self.__secs.get()
for row in self.__buttons:
for button in row:
if button.mine:
button['text'] = 'X'
if self.__scores.eligible(score):
name = askstring('New Record', 'What is your name?')
if name is None:
name = 'Anonymous'
self.__scores.add(name, score)
else:
showinfo('You did not get on the high score table.')
HighScoreView(self, 'High Scores', self.__scores.listing())
def __total(self, x, y):
count = 0
for x_offset in range(-1, 2):
x_index = x + x_offset
for y_offset in range(-1, 2):
y_index = y + y_offset
if 0 <= x_index < self.__width and 0 <= y_index < self.__height:
count += self.__buttons[y_index][x_index].mine
if not count:
self.__propagate(x, y)
return count
def __propagate(self, x, y):
for x_offset in range(-1, 2):
x_index = x + x_offset
for y_offset in range(-1, 2):
y_index = y + y_offset
if 0 <= x_index < self.__width and 0 <= y_index < self.__height:
self.__push(x_index, y_index, False)
def __build_mines(self):
mines = [True] * self.__mines
empty = [False] * (self.__width * self.__height - self.__mines)
total = mines + empty
random.shuffle(total)
iterator = iter(total)
for row in self.__buttons:
for button in row:
button.mine = next(iterator)
button.pushed = False
button.blink_handle = None
################################################################################
class ScoreTable:
def __init__(self, size=10):
self.__data = {999: [''] * size}
def add(self, name, score):
assert self.eligible(score)
if score in self.__data:
self.__data[score].insert(0, name)
else:
self.__data[score] = [name]
if len(self.__data[max(self.__data)]) == 1:
del self.__data[max(self.__data)]
else:
del self.__data[max(self.__data)][-1]
def eligible(self, score):
return score <= max(self.__data)
def listing(self):
for key in sorted(self.__data.keys()):
for name in self.__data[key]:
yield name, key
def load(self, filename):
self.__data = eval(open(filename, 'r').read())
def save(self, filename):
open(filename, 'w').write(repr(self.__data))
################################################################################
class HighScoreView(Dialog):
def __init__(self, parent, title, generator):
self.__scores = generator
super().__init__(parent, title)
def body(self, master):
self.__labels = []
for row, (name, score) in enumerate(self.__scores):
label = tkinter.Label(master, text=name)
self.__labels.append(label)
label.grid(row=row, column=0)
label = tkinter.Label(master, text=str(score))
self.__labels.append(label)
label.grid(row=row, column=1)
self.__okay = tkinter.Button(master, command=self.ok, text='Okay')
self.__okay.grid(ipadx=100, columnspan=2, column=0, row=row+1)
return self.__okay
def buttonbox(self):
pass
################################################################################
if __name__ == '__main__':
MineSweep.main(10, 10, 10, 'scores.txt')
Reference: ActiveState Code » Recipes » MineSweep

Categories