Micro:位类而不是全局变量 - micropython

时间:2018-05-01 15:33:02

标签: python memory micropython bbc-microbit

我刚刚在Micro:bit上为一个高中/高中编码俱乐部创造了我的第一个小事实或敢于/旋转瓶子游戏。我想介绍使用oop / classes / objects而不是(dreaded)全局变量。游戏在https://create.withcode.uk/之类的模拟器上运行得很好,但在Micro:bit本身上,一旦我尝试将任何东西放入类中,我就会遇到内存分配错误。微比特的16KB RAM是不够的?或者我正确地宣布课程?

来自前端和一些PHP / SQL,我是一个Python /内存知识菜鸟,所以任何帮助都表示赞赏。

如果我在每个功能中使用全局变量,它可以正常工作。

以下是代码:

from microbit import *
import random

#timer current function

#Global variables
class game:
    gsTime = 3000
    timerPrev = 0
    numOfPlayers = 0
    maxPlayers = 8
    stage = 'start'
    minSpinTime = 3000

class player:
    #Which player is currently selected
    selected = 0

    #Player position display
    def pos1(): display.set_pixel(2, 4, 9)
    def pos2(): display.set_pixel(2, 0, 9)
    def pos3(): display.set_pixel(0, 2, 9)
    def pos4(): display.set_pixel(4, 2, 9)
    def pos5(): display.set_pixel(0, 4, 9)
    def pos6(): display.set_pixel(4, 0, 9)
    def pos7(): display.set_pixel(0, 0, 9)
    def pos8(): display.set_pixel(4, 4, 9)

    #Array of all player positions
    positions = [
        [pos1, 1, Image.ARROW_S],
        [pos2, 5, Image.ARROW_N],
        [pos3, 3, Image.ARROW_W],
        [pos4, 7, Image.ARROW_E],
        [pos5, 2, Image.ARROW_SW],
        [pos6, 6, Image.ARROW_NE],
        [pos7, 4, Image.ARROW_NW],
        [pos8, 8, Image.ARROW_SE]
    ]
    positionsOrdered = []

class buttons:
    pressed = False

class spinner:
    completeSpins = 0
    isCompleteSpin = False
    rdTime = 0
    stage = 'start'
    stageStarted = False

gameCall = game()
playerCall = player()
buttonsCall = buttons()
spinnerCall = spinner()

#Return a random range of numbers
def rdRange(minMult,maxMult,base):
    return random.randint(base*minMult, base*maxMult)

#return sort key of list
def getKey(item):
    return item[1]

#Timer function
def timer(timeElapsed, onCompleteFunc):
    if running_time() - gameCall.timerPrev >= timeElapsed:
        onCompleteFunc()

#Position Players Start is true
def positionPlayersStartTrue():
    game.stage = 'positionPlayers'

def selectNumOfPlayers(gteOrLte):
    game.timerPrev = running_time()
    if gteOrLte == 'gte':
        if gameCall.numOfPlayers >= gameCall.maxPlayers:
            game.numOfPlayers = 1
        else:
            game.numOfPlayers += 1
    else:
        if gameCall.numOfPlayers <= 1:
            game.numOfPlayers = maxPlayers
        else:
            game.numOfPlayers -= 1
    display.show(str(gameCall.numOfPlayers)) #Have to convert int to string before passing to display.show func
    buttons.pressed = True

#Ask for number of players up to maxPlayers.
def setPlayerNum():
    #If B is pressed increment by 1 up the max players and cycle back to 1
    if button_b.was_pressed():
        selectNumOfPlayers('gte')
    #If A is pressed decrement by 1 down to 1 and then cycle back to maxPlayers var
    elif button_a.was_pressed():
        selectNumOfPlayers('lte')
    elif buttonsCall.pressed == False:
        #Ask how many players
        display.show('#?')
    else:
        timer(gameCall.gsTime, positionPlayersStartTrue)

#display the position of players
def positionPlayers():
    buttons.pressed = False

    display.clear()
    for i in range(gameCall.numOfPlayers):
        el = player.positions[i]
        player.positionsOrdered.append(el)
        el[0]()
    player.positionsOrdered.sort(key=getKey)
    while buttonsCall.pressed == False:
        startSpin()

#start the spin - useful for starting the spin after one spin was complete too
def startSpin():
    if button_a.was_pressed() or button_b.was_pressed():
        buttons.pressed = True
        game.stage = 'spin'

#Spin start
def spin():
    if spinnerCall.stage == 'start' and spinnerCall.stageStarted == False:
        game.timerPrev = running_time()
        spinner.rdTime = rdRange(200, 700, gameCall.numOfPlayers)
        spinner.stageStarted = True
        print(spinner.rdTime)
    for i in range(gameCall.numOfPlayers):
        display.clear()
        el = player.positionsOrdered[i]
        el[0]()
        if i + 1 == gameCall.numOfPlayers:
            spinner.completeSpins += 1
            spinner.isCompleteSpin = True
        else:
            spinner.isCompleteSpin = False
        if spinnerCall.stage == 'start':
            if (running_time() - gameCall.timerPrev >= (gameCall.minSpinTime + spinnerCall.rdTime)) and (spinnerCall.isCompleteSpin == True):
                spinner.stage = 'slow'
                spinner.stageStarted = False
            sleep(200)
        #Slower spin to emulate spinner slowing down as it comes near to stopping. Should probably use some clever-er maths here instead.
        elif spinner.stage == 'slow':
            if spinnerCall.stageStarted == False:
                game.timerPrev = running_time()
                spinner.rdTime = rdRange(500, 900, gameCall.numOfPlayers)
                spinner.stageStarted = True
                print(spinnerCall.rdTime)
            if running_time() - gameCall.timerPrev >= spinnerCall.rdTime:
                spinner.stage = 'stop'
                spinner.stageStarted = False
            sleep(400)
        elif spinner.stage == 'stop':
            player.selected = i
            game.stage = 'selectedPlayer'
            # reset spinner stage for next spin
            spinner.stage = 'start'
            break

#Player has been selected
def selectedPlayer():
    el = playerCall.positionsOrdered[playerCall.selected]
    sleep(200)
    display.show(el[2])
    sleep(200)
    display.clear()


while True:
    #CALL FUNCTIONS
    if gameCall.stage == 'start':
        setPlayerNum()
    elif gameCall.stage == 'positionPlayers' and buttonsCall.pressed == True:
        positionPlayers()
    elif gameCall.stage == 'spin':
        spin()
    elif gameCall.stage == 'selectedPlayer':
        #print('this one is selected ', playerCall.selected)
        selectedPlayer()
        #start spin again if button is pressed
        startSpin()

1 个答案:

答案 0 :(得分:0)

您的代码太大了,无法容纳微比特。微比特受16KB of RAM的限制。要减小代码的大小,您可以:

  1. minify直接从Mu编辑器中使用,或使用任何其他压缩程序lib
  2. 缩小变量名
  3. 删除评论