You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

174 lines
6.0 KiB

#!/usr/bin/env python3
# MIT License
#
# Copyright (c) 2023 Eugenio Parodi <ceccopierangiolieugenio AT googlemail DOT com>
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
import sys, os, math
from dataclasses import dataclass
sys.path.append(os.path.join(sys.path[0],'../../../libs/pyTermTk'))
import TermTk as ttk
@dataclass
class BreakOutParams():
colors = {
'lines': [
ttk.TTkColor.fg("#FF0000"),
ttk.TTkColor.fg("#FF0000"),
ttk.TTkColor.fg("#FF8800"),
ttk.TTkColor.fg("#FF8800"),
ttk.TTkColor.fg("#00FF00"),
ttk.TTkColor.fg("#00FF00"),
ttk.TTkColor.fg("#FFFF00"),
ttk.TTkColor.fg("#FFFF00")],
'bar' : ttk.TTkColor.fg("#0088FF"),
}
delay: float = 0.05
lineBlocks: int = 14
blocksOffset: int = 5
size: tuple([int,int]) = (lineBlocks*8-1, blocksOffset+8+17)
# The ball use a float
# It ijs rasterized in the paint
ballPos = [[20,blocksOffset+10],[math.sin(math.pi/4),math.cos(math.pi/4)]]
barSize: int = 20
barPos: int = (size[0]-barSize)//2
class BreakOutDisplay(ttk.TTkWidget):
_params = BreakOutParams()
_blocks = []
def __init__(self, **kwargs):
size = self._params.size
self._initBlocks()
super().__init__(**kwargs|{"size":size,"minSize":size,"maxSize":size})
self._timer = ttk.TTkTimer()
self._timer.timeout.connect(self._timerEvent)
self._timer.start(self._params.delay)
def _initBlocks(self):
self._blocks = [
[True for _ in range(self._params.lineBlocks)]
for _ in range(8)]
@ttk.pyTTkSlot()
def _timerEvent(self):
w,h = self._params.size
[posx,posy],[vx,vy] = self._params.ballPos
newposx=posx+vx
newposy=posy+vy
lineBlocks = self._params.lineBlocks
blocksOffset = self._params.blocksOffset
barPos = self._params.barPos
barSize = self._params.barSize
# Check if the border is hit:
if newposx >= w: vx=-abs(vx)
elif newposx <= 0: vx= abs(vx)
if newposy >= h: vy=-abs(vy)
elif newposy <= 0: vy= abs(vy)
# Check if a block is hit:
# get the block
bx, by = int(newposx)//8, int(newposy)-blocksOffset
if 0 <= by < 8:
if 0 <= bx < lineBlocks:
if self._blocks[by][bx]:
self._blocks[by][bx] = False
# check if coming from down:
if vy < 0 and by==7 or (by<7 and not self._blocks[by+1][bx]):
vy=abs(vy)
# check if coming from up:
elif vy > 0 and by==0 or (by>0 and not self._blocks[by-1][bx]):
vy=-abs(vy)
# check if coming from left:
elif vx > 0 and bx==0 or (bx>0 and not self._blocks[by][bx-1]):
vx=-abs(vx)
else:
vx= abs(vx)
# Check if the bar is hit:
if newposy >= h-1:
if barPos < newposx < barPos+barSize:
poff = newposx-barPos
prel = poff-barSize/2
delta = prel/barSize
vx = math.sin(math.pi*delta)
vy = -math.cos(math.pi*delta)
# Force a cap on the vertical speed
vy = min(-1,vy)
posx=posx+vx
posy=posy+vy
self._params.ballPos = [[posx,posy],[vx,vy]]
self._timer.start(self._params.delay)
self.update()
def mouseMoveEvent(self, evt) -> bool:
w = self._params.size[0]
barsize = self._params.barSize
self._params.barPos = min(max(0,evt.x-barsize//2),w-barsize)
self.update()
def paintEvent(self, canvas: ttk.TTkCanvas):
colors = self._params.colors
w,h = self._params.size
lineBlocks = self._params.lineBlocks
blocksOffset = self._params.blocksOffset
barPos = self._params.barPos
barSize = self._params.barSize
posx,posy = self._params.ballPos[0]
posx = int(posx)
posy = int(posy)
for by in range(8):
for bx in range(lineBlocks):
if self._blocks[by][bx]:
canvas.drawText(pos=(bx*8,by+blocksOffset),
text=''*7,
color=colors['lines'][by])
canvas.drawText(
pos=(barPos,h-1),
text=''+''*(barSize-2)+'',
color=colors['bar'])
ball = ['','',
'',''][(posx%2)+2*(posy%2)]
canvas.drawText(
pos=(posx,posy),
text=ball)
root = ttk.TTk(title="breakout Demo", mouseTrack=True, layout=ttk.TTkGridLayout())
frame = ttk.TTkFrame(layout=ttk.TTkGridLayout(), title="BreakOuTTk")
breakout = BreakOutDisplay(parent=frame)
root.layout().addWidget(frame,1,1)
root.layout().addItem(ttk.TTkLayout(),0,0)
root.layout().addItem(ttk.TTkLayout(),2,0)
root.layout().addItem(ttk.TTkLayout(),0,2)
root.layout().addItem(ttk.TTkLayout(),2,2)
root.mainloop()