import pygame
import _thread
import time
from random import randint
import math

x = 0
y = 0
WIN_W = 768
WIN_H = 1024
WIN_SCALE = 0.8
FONT_FACE = "lisu"
FRAME_RATE = 20

def ang2rad(ang):
    return math.pi * ang / 180
def rad2ang(rad):
    return 180 * rad / math.pi
def getFrameRate():
    return global0.get('FRAME_RATE', FRAME_RATE)
class HitArea:
    def __init__(self, tp):
        self.type = tp
        pass
    def copy(self):
        return HitArea(self.type)
    def contains(self, x, y):
        return False
    pass
class HitAreaCircle(HitArea):
    def __init__(self, x, y, r):
        HitArea.__init__(self, 'circle')
        self.x = x
        self.y = y
        self.r = r
        pass
    def copy(self):
        return HitAreaCircle(self.type, self.x, self.y, self.r)
    def contains(self, x, y):
        dx = x - self.x
        dy = y - self.y
        r = self.r
        return dx * dx + dy * dy < r * r
    pass
class HitAreaRect(HitArea):
    def __init__(self, x, y, w, h):
        HitArea.__init__(self, 'rect')
        self.x = x
        self.y = y
        self.w = w
        self.h = h
        pass
    def copy(self):
        return HitAreaCircle(self.type, self.x, self.y, self.w, self.h)
    def contains(self, x, y):
        dx = abs(x - self.x)
        dy = abs(y - self.y)
        w = self.w / 2
        h = self.h / 2
        return dx < w and dy < h
    pass

class HitUtil:
    def __init__(self):
        self.checkFuncMap = {
            "circlecircle": self.checkCircleCircle,
            "rectrect": self.checkRectRect,
            "circlerect": self.checkCircleRect,
            "rectcircle": self.checkRectCircle
        }
        pass
    def checkCircleCircle(self, area1, area2):
        dx = area1.x - area2.x
        dy = area1.y - area2.y
        r = area1.r + area2.r
        return dx * dx + dy * dy < r * r
    def checkRectCircle(self, area1, area2):
        dx = abs(area1.x - area2.x)
        dy = abs(area1.y - area2.y)
        w = area1.w / 2
        h = area1.h / 2
        r = area2.r
        if dy < h and dx < r + w:
            return True
        if dx < w and dy < r + h:
            return True
        if dx > w and dy > h and dx < w + r and dy < h + r and dx * dx + dy * dy < r * r:
            return True
        return False
    def checkCircleRect(self, area1, area2):
        return self.checkRectCircle(area2, area1)
    def checkRectRect(self, area1, area2):
        dx = abs(area1.x - area2.x)
        dy = abs(area1.y - area2.y)
        w = abs(area1.w + area2.w) / 2
        h = abs(area1.h + area2.h) / 2
        return dx < w and dy < h
    def checkCollision(self, area1, area2):
        func = self.checkFuncMap.get(area1.type + area2.type) 
        if func:
            return func(area1, area2)
        return False
hitUtil = HitUtil()

class Tween:
    def __init__(self):
        self.target = None
        self.duration = 0
        self.frm = {}
        self.to = {}
        self.t = 0
        pass
    def reset(self):
        self.target = None
        self.duration = 0
        pass
    def init(self, target, duration, frm, to):
        self.target = target
        self.duration = duration
        self.frm = frm
        self.to = to
        self.t = 0
        self.updateAttr()
        pass
    def update(self):
        if self.target:
            self.t += 1000 / getFrameRate()
            self.updateAttr()
            if self.t >= self.duration:
                self.target = None
        pass
    def updateAttr(self):
        f = min(self.t / self.duration, 1.0)
        for k in self.frm:
            v0 = self.frm[k]
            v1 = self.to[k]
            v = v0 + (v1 - v0) * f
            setattr(self.target, k, v)
        pass
    pass

class ArgumnetPaser:
    def __init__(self):
        self.reset()
        pass
    def reset(self):
        self.numbers = []
        self.colors = []
        self.strings = []
        self.functions = []
        self.objects = []
        self.booleans = []
        self.fills = []
        self.arrays = []
        self.fonts = []
        self.directions = []
        self.aligns = []
        self.elements = []
        pass
    def parse(self, *args):
        self.reset()
        for a in args:
            if isinstance(a, int) or isinstance(a, float):
                self.numbers.append(a)
            elif isinstance(a, str):
                self.strings.append(a)
                self.parseColor(a)
                self.parseFill(a)
                self.parseFont(a)
                self.parseDirection(a)
                self.parseAlign(a)
            elif isinstance(a, list):
                self.arrays.append(a)
            elif isinstance(a, dict):
                self.objects.append(a)
            elif isinstance(a, DrawingElement):
                self.elements.append(a)
            elif isinstance(a, bool):
                self.booleans.append(a)
            elif callable(a):
                self.functions.append(a)
            pass
        pass
    def parseColor(self, a):
        if a.startswith("#") and len(a) == 4:
            self.colors.append("#{0}{0}{1}{1}{2}{2}".format(a[1],a[2],a[3]))
        elif a.startswith("rgb"):
            c = eval(a[a.find("("):])
            if len(c) >= 4:
                self.colors.append((c[0], c[1], c[2], int(c[3] * 255)))
            else:
                self.colors.append(c)
        elif a in runtime.colors:
            self.colors.append(runtime.colors[a])
        else:
            try:
                pygame.Color(a)
                self.colors.append(a)
            except:
                pass
        pass
    def parseFont(self, a):
        if a in runtime.fonts:
            self.fonts.append(a)
        pass
    def parseFill(self, a):
        if a in runtime.fills:
            self.fills.append(runtime.fills[a])
        pass
    def parseDirection(self, a):
        if a in runtime.directions:
            self.directions.append(a)
        pass
    def parseAlign(self, a):
        if a in runtime.aligns:
            self.aligns.append(a)
        pass
    pass
argumnetPaser = ArgumnetPaser()

class Runtime:
    def __init__(self):
        self.stamps = {}
        self.fills = {}
        self.colors  ={"transparent": (0, 0, 0, 0)}
        self.sounds = {}
        self.songs = {}
        self.fonts = pygame.font.get_fonts()
        self.directions = ['up', 'down', 'left', 'right', 'center', 'north', 'south', 'east', 'west', 'northeast', 'southeast', 'northwest', 'southwest']
        self.aligns = ['left', 'right', 'center']
        self.keys = {
            'left': {'code': 37, 'name':'ArrowLeft'}
            ,'up': {'code': 38, 'name':'ArrowUp'}
            ,'right': {'code': 39, 'name':'ArrowRight'}
            ,'down': {'code': 40, 'name':'ArrowDown'}
        }
        self.MAX_LINE_WIDTH = 40;
        self.MIN_LINE_WIDTH = 0;
        self.INITIAL_LINE_WIDTH = 2;
        pass
    def isUrl(self, name):
        return name.startswith("http:") or name.startswith("https:") or name.startswith("blob:") or name.startswith("data:image")
    def isMy(self):
        return name.find("@") != -1
    def getStampUrl(self, name):
        return self.getAssetUrl(self.stamps, name, "stamps")
    def getSongUrl(self, name):
        return self.getAssetUrl(self.songs, name, "songs")
    def getSoundUrl(self, name):
        return self.getAssetUrl(self.sounds, name, "sounds")
    def getFillUrl(self, name):
        return self.getAssetUrl(self.fills, name, "fills")
    def getAssetUrl(self, dic, name, typ):
        if name in dic:
            return dic[name]
        return name
    def getKey(self, name, code):
        if name in self.keys:
            return self.keys[name]
        return {'code': code, 'name': name}
        pass
    pass

class Library:
    def __init__(self):
        self.sceneStack = []
        self.largestZ = 0
        self.bgColor = "white"
        self.bgUrl = ''
        self.bgImg = None
        self.lineWidth = runtime.INITIAL_LINE_WIDTH
        self.initialLineColor = "black"
        self.initialFillColor = "black"
        self.lineColor = self.initialLineColor
        self.fillColor = self.initialFillColor
        self.cursorX = WIN_W / 2
        self.cursorY = WIN_H / 2
        pass
    def setLineWidth(self, value):
        self.lineWidth = min(runtime.MAX_LINE_WIDTH, max(value, runtime.MIN_LINE_WIDTH))
        
    def fill(self, *args):
        self.bgColor = "white"
        self.bgUrl = ''
        self.bgImg = None
        argumnetPaser.parse(*args)
        if len(argumnetPaser.numbers) >= 3:
            self.bgColor = pygame.Color(*argumnetPaser.numbers)
        elif len(argumnetPaser.numbers) > 0:
            self.bgColor = argumnetPaser.numbers[0]
        elif len(argumnetPaser.colors) > 0:
            self.bgColor = argumnetPaser.colors[0]
        elif len(argumnetPaser.fills) > 0:
            self.bgUrl = argumnetPaser.fills[0]
            self.bgImg = pygame.image.load(self.bgUrl)
        pass
    def update(self):
        for ele in self.sceneStack:
            if not ele.hidden:
                ele.update()
        pass
    def draw(self, screen):
        self.lineColor = self.initialLineColor
        self.fillColor = self.initialFillColor
        screen.fill(self.bgColor)
        if self.bgImg != None:
            screen.blit(self.bgImg, pygame.Rect(0, 0, WIN_W * WIN_SCALE, WIN_H * WIN_SCALE))
        for ele in self.sceneStack:
            if not ele.hidden:
                ele.draw(screen)
        pass
    def add(self, ele):
        self.sceneStack.append(ele)
        self.largestZ += 1
        ele.z = self.largestZ
        pass
    def reset(self, color = None):
        self.largestZ = 0
        self.sceneStack = []
        pass
    def front(self, ele):
        if ele in self.sceneStack:
            if self.sceneStack[len(self.sceneStack)-1] != ele:
                self.sceneStack.remove(ele)
                self.sceneStack.append(ele)
                self.updateZ()
        pass
    def back(self, ele):
        if ele in self.sceneStack:
            if self.sceneStack[0] != ele:
                self.sceneStack.remove(ele)
                self.sceneStack.insert(0, ele)
                self.updateZ()
        pass
    def updateZ(self):
        i = 0
        for ele in self.sceneStack:
            i += 1
            ele.z = i
        pass
    def find(self, name):
        result = []
        for ele in self.sceneStack:
            if ele.name == name:
                result.append(ele)
        return result
    def tap(self):
        global x, y
        for ele in reversed(self.sceneStack):
            if ele.tap and not ele.hidden and ele.contains(x, y):
                ele.tap()
        pass
    pass

class SoundManager:
    def __init__(self):
        pass
    def sound(self, name, volume = 100, repeat = 1):
        pass
    def silence(self):
        pass
    pass

def sound(name, volume = 100, repeat = 1):
    soundManager.sound(name, volume, repeat)
    pass

def song(name, volume = 100):
    sound(name, volume, 99999999)
    pass
    
def silence():
    soundManager.silence()
    pass

def _delay(func, milliseconds, *args):
    time.sleep(milliseconds/1000)
    func(*args)
    pass

def delay(function, milliseconds, *args):
    try:
       _thread.start_new_thread(_delay, (function, milliseconds) + args)
    except:
       pass
    pass

def distance(a, b):
    return a - b

def find(name):
    return library.find(name)

def look(x, y):
    return peek(x, y)

def peek(x, y):
    global screen
    return screen.get_at(x, y)

def offscreen(*args):
    # stamp
    # x, y
    pass

def random(*args):
    if len(args) == 0:
        return randint(0, 9)
    if len(args) == 1:
        return randint(0, args[0])
    return randint(args[0], args[1])

def repeat(function, count, *args):
    for i in range(count):
        function(*args)
    pass

def reset(color = None):
    library.reset(color)
    pass

def color(*args):
    pass

def fill(*args):
    library.fill(*args)
    pass

def box(*args, **kwargs):
    return Box(*args, **kwargs)

def circle(*args, **kwargs):
    return Circle(*args, **kwargs)

def line(*args, **kwargs):
    return Line(*args, **kwargs)

def stamp(*args, **kwargs):
    return Stamp(*args, **kwargs)

def text(*args, **kwargs):
    return Text(*args, **kwargs)

class DrawingElement:
    def __init__(self, x = WIN_W / 2, y = WIN_H / 2):
        self.x = x
        self.y = y
        self.z = 0
        self.rotation = 0
        self.width = 0
        self.height = 0
        self.hidden = False
        self.flipped = False
        self.fontSize = 30
        self.name = ''
        self.fillColor = ''
        self.lineColor = ''
        self.solidFill = True
        self.moveAnimaion = Tween()
        self.sizeAnimation = Tween()
        self.rotateAnimation = Tween()
        library.add(self)
        pass
    def hitArea(self):
        return HitAreaRect(self.x, self.y, self.width, self.height)
    def setLineColor(self, lineColor):
        if lineColor:
            library.lineColor = lineColor
        pass
    def setFillColor(self, fillColor):
        if fillColor:
            library.fillColor = fillColor
        pass
    def contains(self, x, y):
        dx = x - self.x
        dy = y - self.y
        return abs(dx) < self.width / 2 and abs(dy) < self.height / 2
    def update(self):
        self.moveAnimaion.update()
        self.sizeAnimation.update()
        self.rotateAnimation.update()
        pass
    def draw(self, screen):
        pass
    def aim(self, x, y):
        pass
    
    def back(self):
        library.back(self)
        pass
    
    def front(self):
        library.front(self)
        pass
    
    def change(self, *args, **kwargs):
        self.changeColor(*args)
        pass
    def changeColor(self, *args, **kwargs):
        argumnetPaser.parse(*args)
        if len(argumnetPaser.colors) == 1:
            self.lineColor = argumnetPaser.colors[0]
            self.fillColor = argumnetPaser.colors[0]
        elif len(argumnetPaser.colors) > 1:
            self.lineColor = argumnetPaser.colors[1]
            self.fillColor = argumnetPaser.colors[0]
        if len(argumnetPaser.booleans) > 0:
            self.solidFill = argumnetPaser.booleans[0]
        pass
    def dance(self):
        pass
    
    def explode(self, name, callback = None, scale = 2.5):
        pass
    
    def pop(self, callback = None):
        self.explode('pop', callback);
        pass
    
    def splash(self, callback = None):
        self.explode('splash', callback);
        pass
    
    def burn(self, callback = None):
        self.explode('burn', callback);
        pass
    
    def pow(self, callback = None):
        self.explode('pow', callback);
        pass
    
    def flip(self):
        self.flipped = not self.flipped
        pass
    
    def hide(self):
        self.hidden = True
        pass
    
    def show(self):
        self.hidden = False
        pass
    
    def hits(self, *args):
        if self.hidden:
            return False
        argumnetPaser.parse(*args)
        if len(argumnetPaser.numbers) >= 2:
            return self.contains(argumnetPaser.numbers[0], argumnetPaser.numbers[1])
        if len(argumnetPaser.strings) > 0:
            arr = []
            name = argumnetPaser.strings[0]
            for ele in library.sceneStack:
                if not ele.hidden and ele.name == name and self.checkCollisionEleEle(self, ele):
                    arr.append(ele)
            return arr
        if len(argumnetPaser.elements) > 0:
            return self.checkCollisionEleEle(self, argumnetPaser.elements[0])
        pass
    def checkCollisionEleEle(self, ele1, ele2):
        return hitUtil.checkCollision(ele1.hitArea(), ele2.hitArea())
    def move(self, x, y, milliseconds = 0, *args):
        self.moveAnimaion.reset()
        if milliseconds and milliseconds > 0:
            self.moveAnimaion.init(self, milliseconds, {"x": self.x, "y": self.y}, {"x": x, "y": y})
        else:
            self.x = x
            self.y = y
        pass
    
    def rotate(self, angle, milliseconds = 0):
        # direction, degrees, milliseconds
        pass
    
    def sing(self, volume = 100, loops = 1):
        pass
    
    def size(self, pixels, milliseconds = 0):
        pass
    
    def swim(self):
        pass
    
    def tap(self):
        pass
    
    def wrap(self):
        pass
    
    def onTick(self, now):
        pass
    pass

class Box(DrawingElement):
    def __init__(self, x, y, width, height, *args):
        DrawingElement.__init__(self, x + width / 2 , y + height / 2) # xdf库的bug
        self.width = width
        self.height = height
        self.change(*args)
        pass
    def size(self, *args):
        self.sizeAnimation.reset()
        argumnetPaser.parse(*args)
        w = self.width
        h = self.height
        f = h / w
        milliseconds = 0
        if len(argumnetPaser.numbers) == 0:
            w = random(20, 500)
            h = w * f
        elif len(argumnetPaser.numbers) == 1:
            w = argumnetPaser.numbers[0]
            h = w * f
        elif len(argumnetPaser.numbers) == 2:
            w = argumnetPaser.numbers[0]
            h = argumnetPaser.numbers[1]
        else:
            w = argumnetPaser.numbers[0]
            h = argumnetPaser.numbers[1]
            milliseconds = argumnetPaser.numbers[2]
        if milliseconds > 0:
            self.sizeAnimation.init(self, milliseconds, {"width": self.width, "height": self.height}, {"width": w, "height": h})
        else:
            self.width = w
            self.height = h
        pass
    def draw(self, screen):
        super().draw(screen)
        self.setLineColor(self.lineColor)
        self.setFillColor(self.fillColor)
        lineW = int(library.lineWidth * WIN_SCALE + 0.5)
        w = self.width * WIN_SCALE
        h = self.height * WIN_SCALE
        surface = pygame.Surface((int(w + 1), int(h + 1)), pygame.SRCALPHA)
        rect = pygame.Rect(0, 0, w, h)
        if self.solidFill:
            pygame.draw.rect(surface, library.fillColor, rect)
        pygame.draw.rect(surface, library.lineColor, rect, lineW)
        p = (self.x * WIN_SCALE - w / 2, self.y * WIN_SCALE - h / 2)
        screen.blit(surface, p)
    pass

class Circle(DrawingElement):
    def __init__(self, x, y, *args):
        #radius = None, color = None, lineColor = None
        DrawingElement.__init__(self, x, y)
        self.radius = 100
        argumnetPaser.parse(*args)
        if len(argumnetPaser.numbers) > 0:
            self.radius = argumnetPaser.numbers[0]
        self.change(*args)
        self.width = self.height = self.radius * 2
        pass
    def hitArea(self):
        return HitAreaCircle(self.x, self.y, self.radius)
    def update(self):
        super().update()
        self.width = self.height = self.radius * 2
        pass
    def contains(self, x, y):
        dx = x - self.x
        dy = y - self.y
        r = self.radius
        return dx * dx + dy * dy < r * r
    def size(self, size, milliseconds = 0):
        self.sizeAnimation.reset()
        if milliseconds and milliseconds > 0:
            self.sizeAnimation.init(self, milliseconds, {"radius": self.radius}, {"radius": size})
        else:
            if size and size > 0:
                self.radius = size
            else:
                self.radius = random(20, 500)
        self.width = self.height = self.radius * 2
        pass
    def draw(self, screen):
        super().draw(screen)
        self.setLineColor(self.lineColor)
        self.setFillColor(self.fillColor)
        r = self.radius * WIN_SCALE
        w = int(r * 2 + 1)
        p = (r, r)
        surface = pygame.Surface((w, w), pygame.SRCALPHA)
        if self.solidFill:
            pygame.draw.circle(surface, library.fillColor, p, r)
        pygame.draw.circle(surface, library.lineColor, p, r, int(library.lineWidth * WIN_SCALE + 0.5))
        p = (self.x * WIN_SCALE - r, self.y * WIN_SCALE - r)
        screen.blit(surface, p)
    pass

class Line(DrawingElement):
    def __init__(self, *args):
        argumnetPaser.parse(*args)
        x = 0
        y = 0
        x2 = 0
        y2 = 0
        lineColor = ''
        lineWidth = 0
        if len(argumnetPaser.colors) > 0:
            lineColor = argumnetPaser.colors[0]
        lineWidth = library.lineWidth
        if len(argumnetPaser.numbers) % 2 == 1:
            lineWidth = argumnetPaser.numbers[-1]
            library.setLineWidth(lineWidth)
        if len(argumnetPaser.numbers) < 2:
            return
        if len(argumnetPaser.numbers) // 2 == 1:
            x = library.cursorX
            y = library.cursorY
            x2 = argumnetPaser.numbers[0]
            y2 = argumnetPaser.numbers[1]
        elif len(argumnetPaser.numbers) // 2 >= 2:
            x = argumnetPaser.numbers[0]
            y = argumnetPaser.numbers[1]
            x2 = argumnetPaser.numbers[2]
            y2 = argumnetPaser.numbers[3]
        DrawingElement.__init__(self, x, y)
        self.x2 = x2
        self.y2 = y2
        self.lineColor = lineColor
        self.lineWidth = lineWidth
        pass
    def change(self, lineColor):
        self.lineColor = lineColor
        pass
    def draw(self, screen):
        super().draw(screen)
        self.setLineColor(self.lineColor)
        p0 = (self.x * WIN_SCALE, self.y * WIN_SCALE)
        p1 = (self.x2 * WIN_SCALE, self.y2 * WIN_SCALE)
        pygame.draw.line(screen, library.lineColor, p0, p1, int(self.lineWidth * WIN_SCALE + 0.5))
        pass
    def move(self, *args):
        argumnetPaser.parse(*args)
        if len(argumnetPaser.numbers) >= 4:
            self.x = argumnetPaser.numbers[0]
            self.y = argumnetPaser.numbers[1]
            self.x2 = argumnetPaser.numbers[2]
            self.y2 = argumnetPaser.numbers[3]
        elif len(argumnetPaser.numbers) >= 2:
            dx = self.x2 - self.x
            dy = self.y2 - self.y
            self.x = argumnetPaser.numbers[0]
            self.y = argumnetPaser.numbers[1]
            self.x2 = self.x + dx
            self.y2 = self.y + dy
        pass
    def rotate(self, angle, milliseconds = 0):
        self.rotateAnimation.reset()
        if milliseconds > 0:
            self.rotateAnimation.init(self, milliseconds, {"angle": self.angle}, {"angle": angle})
        else:
            self.angle = angle
        pass
    @property
    def angle(self):
        return self.rotation
    @angle.setter
    def angle(self, value):
        d = self.length
        value = ang2rad(value - 90)
        self.x2 = self.x + math.cos(value) * d
        self.y2 = self.y + math.sin(value) * d
        pass
    @property
    def length(self):
        dx = self.x2 - self.x
        dy = self.y2 - self.y
        return math.sqrt(dx * dx + dy * dy)
    @length.setter
    def length(self, value):
        dx = self.x2 - self.x
        dy = self.y2 - self.y
        d = math.sqrt(dx * dx + dy * dy)
        f = value / d
        self.x2 = self.x + dx * f
        self.y2 = self.y + dy * f
        pass
        
    def size(self, length, milliseconds = 0):
        self.sizeAnimation.reset()
        if milliseconds > 0:
            self.sizeAnimation.init(self, milliseconds, {"length": self.length}, {"length": length})
        else:
            self.length = length
        pass
    pass

class Stamp(DrawingElement):
    def __init__(self, name, x = WIN_W / 2, y = WIN_H / 2, size = None):
        DrawingElement.__init__(self, x, y)
        self.change(name)
        self.width = self.img.get_width()
        self.height = self.img.get_height()
        if size != None:
            self.size(size)
        pass
    def sing(self, volume = 100, loops = 1):
        sound(self.name, volume, loops)
        pass
    def draw(self, screen):
        super().draw(screen)
        img = self.img
        if self.flipped:
            img = pygame.transform.flip(img, True, False)
        img = pygame.transform.scale(img, (self.width * WIN_SCALE, self.height * WIN_SCALE))
        img = pygame.transform.rotate(img, -self.rotation)
        rect = img.get_rect()
        pos = (self.x * WIN_SCALE - rect.width / 2 , self.y * WIN_SCALE - rect.height / 2)
        screen.blit(img, pos)
        #pygame.draw.rect(screen, (255, 0, 0), pygame.Rect(pos[0], pos[1], rect.width, rect.height), 2)
        pass
    
    def rotate(self, angle, milliseconds = 0):
        if milliseconds and milliseconds > 0:
            pass
        else:
            self.rotation = angle
        pass
    
    def size(self, pixels, milliseconds = 0):
        if milliseconds and milliseconds > 0:
            pass
        else:
            self.width = self.height = pixels
        pass
    def change(self, name):
        self.name = name
        self.url = runtime.getStampUrl(name)
        self.img = pygame.image.load(self.url)
        #self.width = self.img.get_width()
        #self.height = self.img.get_height()
    pass

class Text(DrawingElement):
    def __init__(self, txt, *args):
        DrawingElement.__init__(self)
        argumnetPaser.parse(*args)
        self.fontFace = FONT_FACE
        self.fontSize = 40
        self.textAlign = "left"
        self.txt = str(txt)
        self.fillStyle = "black"
        if len(argumnetPaser.fonts) > 0:
            self.fontFace = argumnetPaser.fonts[0]
        if len(argumnetPaser.colors) > 0:
            self.fillStyle = argumnetPaser.colors[0]
        if len(argumnetPaser.aligns) > 0:
            self.textAlign = argumnetPaser.aligns[0]
        if len(argumnetPaser.numbers) == 1:
            self.fontSize = argumnetPaser.numbers[0]
        elif len(argumnetPaser.numbers) == 2:
            self.x = argumnetPaser.numbers[0]
            self.y = argumnetPaser.numbers[1]
        elif len(argumnetPaser.numbers) >= 3:
            self.x = argumnetPaser.numbers[0]
            self.y = argumnetPaser.numbers[1]
            self.fontSize = argumnetPaser.numbers[2]
        self.rect = HitAreaRect(self.x, self.y, 0, 0)
        pass
    def hitArea(self):
        return self.rect.copy()
    def contains(self, x, y):
        return self.rect.contains(x, y)
    def draw(self, screen):
        font = pygame.font.SysFont(self.fontFace, int(self.fontSize * WIN_SCALE + 0.5))
        txtsurf = font.render(self.txt, True, self.fillStyle)
        w = txtsurf.get_width()
        h = txtsurf.get_height()
        x = 0
        if self.textAlign == 'right':
            x = w
        elif self.textAlign == 'center':
            x = w / 2
        screen.blit(txtsurf, (self.x * WIN_SCALE - x, self.y * WIN_SCALE- h))
        # todo 碰撞区域跟新，放在这里，更新不及时
        self.rect.x = self.x
        self.rect.y = self.y
        self.rect.w = w / WIN_SCALE
        self.rect.h = h / WIN_SCALE
        pass
    def change(self, txt):
        self.txt = str(txt)
    pass

soundManager = SoundManager()
runtime = Runtime()
library = Library()

import pygame
isRunning = False
screen = None
global0 = {}
isMouseDown = False
downTime = 0
def callGlobal(name, *args):
    func = global0.get(name)
    if func:
        func(*args)
    pass
def handleEvent():
    global isMouseDown,downTime
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            global isRunning
            isRunning = False
            pass
        elif event.type == pygame.MOUSEBUTTONDOWN:
            isMouseDown = True
            downTime = time.time()
            callGlobal('touch')
            pass
        elif event.type == pygame.MOUSEBUTTONUP:
            isMouseDown = False
            t = time.time()
            callGlobal('untouch')
            if t - downTime < 0.400:
                callGlobal('tap')
                library.tap()
            pass
        elif event.type == pygame.MOUSEMOTION:
            if isMouseDown:
                callGlobal('touching')
            pass
        elif event.type == pygame.KEYDOWN:
            key=pygame.key.name(event.key)
            key = runtime.getKey(key, event.key)
            callGlobal('keydown', key['code'], key['name'])
            pass
        if event.type == pygame.KEYUP:
            key=pygame.key.name(event.key)
            key = runtime.getKey(key, event.key)
            callGlobal('keyup', key['code'], key['name'])
            pass
    pass

def go(glb):
    global screen, isRunning, global0, WIN_SCALE, FONT_FACE
    global0 = glb
    WIN_SCALE = global0.get("WIN_SCALE", WIN_SCALE)
    FONT_FACE = global0.get("FONT_FACE", FONT_FACE)
    #
    pygame.init()
    screen = pygame.display.set_mode((WIN_W * WIN_SCALE, WIN_H * WIN_SCALE))
    pygame.key.set_repeat(500, 50)
    isRunning = True
    clock = pygame.time.Clock()
    while isRunning:
        global x,y
        x,y = pygame.mouse.get_pos()
        x /= WIN_SCALE
        y /= WIN_SCALE
        global0["x"] = x
        global0["y"] = y
        handleEvent()
        callGlobal("loop")
        library.update()
        library.draw(screen)
        pygame.display.flip()
        clock.tick(getFrameRate()) 
    pygame.quit()
    pass
