Другое

Почему в MicroStudio отображается только экран магазина?

Решение проблемы с отображением только магазина вместо игры в MicroScript. Узнайте о правильной организации состояний и исправлении кода.

Помогите с кодом в MicroStudio: почему отображается только экран магазина?

Я пишу игру ‘Space escape’ на языке MicroScript, но столкнулся с проблемой - после инициализации и обновления спрайтов (игрок, монета, здоровье) и отображения счета, игра показывает только экран магазина, а не основной игровой процесс.

Вот мой код:

microscript
init = function()
  Quick.init()

  player = Quick.addSprite("player", 0, 0, 52, 32)
  coin = Quick.addSprite("coin", 100, 0, 8, 8)
  health = Quick.addSprite("health", 170, -80, 50, 50)
  score = 0

  title = true
end

update = function()
  Quick.update()
  player_control()
  coin_update()

  if playButton then
    title = false
  end
end

draw = function()
  if title == false then
    Quick.draw()
    screen.drawText("score: "+score, 0, 50, 20, "green")
  elsif title == true then
    screen.clear("black")
    screen.drawText("Space escape", 0, 50, 30, "red")
    playButton = IMGUI.button("play", 0, 0, 100, 20)
    shopButton = IMGUI.button("shop", 0, -30, 50, 10)
  end
end

draw = function()
  if title == false then
    Quick.draw()
    screen.drawText("ты молодец", 160, 75, 15, "red")
  elsif title == true then
    screen.clear("green")
    screen.drawText("shop", 160, 90, 30, "blue")
    screen.drawText("money", 150, -80, 30, "blue")
    screen.fillRect(0, 0, 250, 150, "red")
  end
end

Проблема в том, что у меня есть две функции draw, и вторая, кажется, переопределяет первую. Как правильно организовать отрисовку разных экранов (меню, магазин, игра) в MicroScript? Почему после нажатия кнопки ‘play’ игра не переходит в основной игровой процесс, а продолжает показывать магазин?

В вашем коде есть две основные проблемы: дублирование функции draw и неправильная организация состояний игры. В MicroScript нельзя объявлять несколько функций с одним и тем же именем - последняя функция переопределит предыдущие.

Содержание


Основные проблемы в вашем коде

  1. Дублирование функции draw - в MicroScript функция, объявленная второй с тем же именем, полностью заменяет предыдущую
  2. Отсутствие правильного управления состояниями - переменная title не переключается правильно между экранами
  3. Неправильная логика кнопки - переменная playButton не сбрасывается после нажатия
  4. Отсутствие инициализации IMGUI - интерфейсные элементы не работают без настройки

Правильная организация состояний в MicroScript

Как показано в примере сообщества MicroStudio, правильный подход - создать отдельные блоки состояний с их собственными функциями:

microscript
// Определяем состояния
titlepage = {}
maingame = {}

// Инициализация каждого состояния
titlepage.init = function()
  // код инициализации меню
end

maingame.init = function()
  // код инициализации игры
end

// Основная инициализация
init = function()
  titlepage.init()  // инициализируем меню
  maingame.init()   // инициализируем игру
  state = titlepage // устанавливаем активное состояние
end

// Обновление активного состояния
update = function()
  state.update() // вызываем update() активного состояния
end

// Отрисовка активного состояния
draw = function()
  state.draw() // вызываем draw() активного состояния
end

Исправленный код для игры “Space escape”

Вот как должен выглядеть ваш исправленный код с правильной организацией состояний:

microscript
// Определяем состояния игры
gameStates = {}

// Состояние меню
gameStates.menu = {
  init = function()
    score = 0
    IMGUI.init()  // инициализируем интерфейс
  end,
  
  update = function()
    // Обработка кнопок
    playButton = IMGUI.button("play", 0, 0, 100, 20)
    shopButton = IMGUI.button("shop", 0, 30, 50, 10)
    
    // Проверяем нажатие кнопки игры
    if playButton then
      gameState = "game"  // переключаемся в игру
    end
    
    if shopButton then
      gameState = "shop"   // переключаемся в магазин
    end
  end,
  
  draw = function()
    screen.clear("black")
    screen.drawText("Space escape", 0, 50, 30, "red")
  end
}

// Состояние игры
gameStates.game = {
  init = function()
    Quick.init()
    
    player = Quick.addSprite("player", 0, 0, 52, 32)
    coin = Quick.addSprite("coin", 100, 0, 8, 8)
    health = Quick.addSprite("health", 170, -80, 50, 50)
    
    player_control()
    coin_update()
  end,
  
  update = function()
    Quick.update()
    player_control()
    coin_update()
  end,
  
  draw = function()
    Quick.draw()
    screen.drawText("score: "+score, 0, 50, 20, "green")
    screen.drawText("ты молодец", 160, 75, 15, "red")
  end
}

// Состояние магазина
gameStates.shop = {
  draw = function()
    screen.clear("green")
    screen.drawText("shop", 160, 90, 30, "blue")
    screen.drawText("money", 150, -80, 30, "blue")
    screen.fillRect(0, 0, 250, 150, "red")
  end
}

// Основные функции
init = function()
  gameState = "menu"  // начинаем с меню
  gameStates[gameState].init()
end

update = function()
  gameStates[gameState].update()
end

draw = function()
  gameStates[gameState].draw()
end

Пример управления несколькими экранами

Как объясняется в статье о простых игровых состояниях, каждое состояние требует разных ресурсов и обработки ввода:

microscript
// Более расширенный пример с несколькими состояниями
stateManager = {
  currentState = null,
  
  switchTo = function(newState)
    // Вызываем очистку текущего состояния
    if self.currentState and self.currentState.cleanup then
      self.currentState.cleanup()
    end
    
    // Переключаем состояние
    self.currentState = newState
    self.currentState.init()
  end,
  
  update = function()
    if self.currentState then
      self.currentState.update()
    end
  end,
  
  draw = function()
    if self.currentState then
      self.currentState.draw()
    end
  end
}

// Состояния
titleScreen = {
  init = function()
    // Загрузка ресурсов меню
  end,
  
  update = function()
    // Обработка ввода для меню
  end,
  
  draw = function()
    // Отрисовка меню
  end,
  
  cleanup = function()
    // Очистка ресурсов меню
  end
}

gameScreen = {
  init = function()
    // Загрузка игровых ресурсов
  end,
  
  update = function()
    // Игровая логика
  end,
  
  draw = function()
    // Отрисовка игры
  end,
  
  cleanup = function()
    // Сохранение игры, очистка ресурсов
  end
}

// Использование
init = function()
  stateManager.switchTo(titleScreen)
end

update = function()
  stateManager.update()
end

draw = function()
  stateManager.draw()
end

Как создать универсальную систему состояний

Для более сложных игр рекомендуется создать полноценный менеджер состояний, как показано в примерах для других игровых движков:

microscript
// Универсальный менеджер состояний
StateManager = {
  states = {},
  currentState = null,
  
  addState = function(name, state)
    self.states[name] = state
  end,
  
  changeState = function(newStateName)
    if self.states[newStateName] then
      if self.currentState and self.currentState.exit then
        self.currentState.exit()
      end
      
      self.currentState = self.states[newStateName]
      if self.currentState.enter then
        self.currentState.enter()
      end
    end
  end,
  
  update = function()
    if self.currentState and self.currentState.update then
      self.currentState.update()
    end
  end,
  
  draw = function()
    if self.currentState and self.currentState.draw then
      self.currentState.draw()
    end
  end
}

// Пример использования
StateManager.addState("menu", {
  enter = function()
    screen.clear("black")
  end,
  
  update = function()
    if IMGUI.button("Start", 100, 100, 100, 30) then
      StateManager.changeState("game")
    end
  end,
  
  draw = function()
    screen.drawText("Main Menu", 100, 50, 24, "white")
  end
})

StateManager.addState("game", {
  enter = function()
    // Инициализация игры
  end,
  
  update = function()
    // Игровая логика
  end,
  
  draw = function()
    // Отрисовка игры
  end,
  
  exit = function()
    // Сохранение прогресса
  end
})

// Основные функции
init = function()
  StateManager.changeState("menu")
end

update = function()
  StateManager.update()
end

draw = function()
  StateManager.draw()
end

Источники

  1. Simple game state management / switching - MicroStudio Community
  2. Simple Game States Tutorial - ohsat.com
  3. microStudio Documentation - microScript cheatsheet
  4. Stackable Screen/State Management - GitHub
  5. Yet Another Multiple States System - PICO-8 Wiki

Заключение

  • Основная проблема - в вашем коде две функции draw, что приводит к переопределению первой второй
  • Правильный подход - использовать систему управления состояниями с отдельными функциями для каждого экрана
  • Рекомендации:
    1. Создайте отдельные объекты для меню, магазина и игры
    2. Используйте единую функцию draw, которая вызывает соответствующий метод текущего состояния
    3. Не забывайте инициализировать IMGUI перед использованием кнопок
    4. Используйте четкие имена состояний для лучшей читаемости кода
  • Следующие шаги - реализуйте систему сохранения/загрузки состояний для более плавного переключения между экранами
Авторы
Проверено модерацией
Модерация