Giter Club home page Giter Club logo

scratch-vm's Introduction

scratch-vm

Scratch VM is a library for representing, running, and maintaining the state of computer programs written using Scratch Blocks.

CI/CD

Installation

This requires you to have Git and Node.js installed.

To install as a dependency for your own application:

npm install scratch-vm

To set up a development environment to edit scratch-vm yourself:

git clone https://github.com/scratchfoundation/scratch-vm.git
cd scratch-vm
npm install

Development Server

This requires Node.js to be installed.

For convenience, we've included a development server with the VM. This is sometimes useful when running in an environment that's loading remote resources (e.g., SVGs from the Scratch server). If you would like to use your modified VM with the full Scratch 3.0 GUI, follow the instructions to link the VM to the GUI.

Running the Development Server

Open a Command Prompt or Terminal in the repository and run:

npm start

Playground

To view the Playground, make sure the dev server's running and go to http://localhost:8073/playground/ - you will be directed to the playground, which demonstrates various tools and internal state.

VM Playground Screenshot

Standalone Build

npm run build
<script src="/path/to/dist/web/scratch-vm.js"></script>
<script>
    var vm = new window.VirtualMachine();
    // do things
</script>

How to include in a Node.js App

For an extended setup example, check out the /src/playground directory, which includes a fully running VM instance.

var VirtualMachine = require('scratch-vm');
var vm = new VirtualMachine();

// Block events
Scratch.workspace.addChangeListener(vm.blockListener);

// Run threads
vm.start();

Abstract Syntax Tree

Overview

The Virtual Machine constructs and maintains the state of an Abstract Syntax Tree (AST) by listening to events emitted by the scratch-blocks workspace via the blockListener. Each target (code-running object, for example, a sprite) keeps an AST for its blocks. At any time, the current state of an AST can be viewed by inspecting the vm.runtime.targets[...].blocks object.

Anatomy of a Block

The VM's block representation contains all the important information for execution and storage. Here's an example representing the "when key pressed" script on a workspace:

{
  "_blocks": {
    "Q]PK~yJ@BTV8Y~FfISeo": {
      "id": "Q]PK~yJ@BTV8Y~FfISeo",
      "opcode": "event_whenkeypressed",
      "inputs": {
      },
      "fields": {
        "KEY_OPTION": {
          "name": "KEY_OPTION",
          "value": "space"
        }
      },
      "next": null,
      "topLevel": true,
      "parent": null,
      "shadow": false,
      "x": -69.333333333333,
      "y": 174
    }
  },
  "_scripts": [
    "Q]PK~yJ@BTV8Y~FfISeo"
  ]
}

Testing

npm test
npm run coverage

Publishing to GitHub Pages

npm run deploy

This will push the currently built playground to the gh-pages branch of the currently tracked remote. If you would like to change where to push to, add a repo url argument:

npm run deploy -- -r <your repo url>

Donate

We provide Scratch free of charge, and want to keep it that way! Please consider making a donation to support our continued engineering, design, community, and resource development efforts. Donations of any size are appreciated. Thank you!

scratch-vm's People

Contributors

adroitwhiz avatar apple502j avatar chrisgarrity avatar cwillisf avatar dependabot-preview[bot] avatar ericrosenbaum avatar evhan55 avatar fsih avatar gnarf avatar greenkeeper[bot] avatar griffpatch avatar hyperobject avatar joker314 avatar kchadha avatar kenny2github avatar khanning avatar knandersen avatar ktbee avatar mzgoddard avatar paulkaplan avatar picklesrus avatar renovate-bot avatar renovate[bot] avatar rschamp avatar semantic-release-bot avatar sillyinventor avatar thebrokenrail avatar thisandagain avatar tmickel avatar towerofnix avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

scratch-vm's Issues

Glow behavior when moving around stacks

Scratch-blocks is very simple about what stacks are glowed - you just tell it which ones to do and it will do it. We need to build in some smart behavior to the VM for when you are moving around executing blocks, which stacks should be glowed. For example, if you start executing a stack, let the execution point go to the bottom of the stack, and then pull off the bottom, the bottom will still be executing, when the top half is the highlighted one :(

Scratch 2.0 has a bunch of bugs here also so it may be tricky to get right, but important, I think.

Implement `interp.redraw` equivalent

In Scratch 2.0, there's a global interpreter flag that tracks whether a block has triggered a sprite's drawn representation to become out-of-date. E.g, a "move 10 steps" block would trigger redraw, but a "set var to 20" wouldn't. The value of this flag determines whether or not a loop yields at the end of a frame (if the interpreter isn't in turbo mode). We need an equivalent flag in scratch-vm, and we can also use something similar to determine whether we should call the renderer's draw method.

https://github.com/LLK/scratch-flash/blob/master/src/interpreter/Interpreter.as#L84

Convert to ES6

Sort out tests and node support for ES6 to ensure that we can still run tests / run the vm headless.

Repeat until should be avaliable

screen shot 2016-06-29 at 11 17 58 am

I think we need [repeat until (...)] blocks in ["scratch3_control.js"](https://github.com/LLK/scratch-vm/blob/develop/src/blocks/scratch3_control.js) `'control_repeat_until': this.repeatUntil`?

Implement custom reporters

We can create a couple of stub blocks in scratch-blocks and start working on this right away, I think.

Single-stepping debug mode

It would be great to have a mode of execution where things are stepped by a button in the VM playground. The button would essentially call stepThreads() with a tiny WORK_TIME, to proceed one block per thread every time the button is pushed.

In the long run, it would be good to have single-stepping mode a la Scratch 1.4

Refactor change listeners into blocks.js

These are in index.js currently and have some duplicated code for flyout vs. workspace blocks. Ideally I'd like to refactor it and move it into the Blocks module.

Use WebWorker when possible

If WebWorkers are available, it would be great to launch the VM in a worker thread instead of in the main thread. It would be good to do this as soon as possible, so we make sure our implementation isn't accidentally doing main-thread-only tasks, and so that we get the timing right across the two threads.

Behavior on tap running stack

This is something that I think we need to resolve eventually. Right now in Scratch, if you click a running stack, that stack stops. But what happens if it was running a long-running block, like "motor on for 5 secs"? In our current model, the motor would stay on, I think... Perhaps tapping a running stack shouldn't stop it, or we need to think about how to implement stopping it.

Add targets associated with blocks and execution context

Need to figure out how to associate blocks with particular targets. As part of this, it would be good to create the "sprite manager" as per our plans, which will store the master copy of data pertaining to all sprites, including x/y position, current costume, etc., and pass this along to the renderer on every frame.

Implement project timer

For the "timer" blocks.

  • Starts counting when the VM is loaded.
  • Resets when a green flag event happens.

Implement yielding reporters that return values

An example of a block that needs this is an "HTTP request" extension block.

How should it work?

Perhaps,

  • Mark the thread as yielded, and don't pop the stack to make sure flow control waits on that block.
  • Add a util.report function that the primitive can execute when it's ready.
  • util.report somehow bubbles up its value into the caller's arguments object.
  • Make sure each reporter is only called once per block execution.

Add block listeners to flyout workspace

  • 1. Context menu needs messages (currently shows up empty).
  • 2. Host from 0.0.0.0 instead of 127.0.0.1.
  • 3. Add documentation about make serve.
  • 4. Add a redirect from / to /playground by default
  • 5. Add listeners for the flyout workspace. The underlying issue has been fixed in scratch-blocks, so this should be possible now.

Turn down intervals

Until we can implement the VM in a WebWorker, running as much computation as we are seems to be hanging the main UI thread...this is mostly visible when dragging blocks around. It won't make it as perfect as we can, but we could improve it slightly by making the blocks execute for less ms.

Reconsider YieldTimer infrastructure

We created this infrastructure quickly to try to support the WeDo prototype. I think it should support our thread timing needs, but we'd like to have a discussion about it before we start building on it too deeply, as it's a little bit messy.

Blocks are sometimes not destroyed properly from representation tree

This seems to happen mostly when you drag a reporter into a shadow block slot.

To reproduce:
-Create a "repeat" block.
-Create an addition block.
-Drag the addition block into the repeat block's shadow space.
-Delete the repeat.

The addition block is still present in the VM's representation.

Implement yielding reporters that block all threads

(e.g., "color touching color" across a thread boundary).

In Scratch 1.0/2.0, this is handled by ensuring that all operations that need to block all threads are actually performed synchronously. So, one way would be to make sure that the reporter doesn't give up the JS execution thread until it gets its answer (while loop?). The other way would be to have a flag on util.yield that specifically disables running other threads until that reporter returns.

VM playground

To accelerate VM playing and develop, we'd like to create a "VM playground."

This will link to scratch-blocks and pre-load a bunch of blocks. Ideally I'd like to create a small tool to explore the AST, step execution and explore the internal state, etc.

Implement "wait until"

Best to do this right away, as it's bending my mind a little bit with our current set-up.

Errors after hooking up flyout events to VM

vm.js:1361 Uncaught TypeError: Cannot read property 'next' of undefined

almost definitely related to my changes. And possibly how flyout blocks produce weird events.

Also, sometimes:
vm.js:1391 Uncaught TypeError: Cannot set property 'topLevel' of undefined

and stacks appears out of sync...

What happened :)

Restructure code-running to handle arguments

Currently, args are patched in for our horizontal prototype implementation.

We need to run blockFunction with some recursive evaluation so that args are processed before being passed to the outer block.

Dealing with hat blocks

How should these be handled in the VM? Should they be done like Scratch 2.0 (where there's an imperative method like allHatsDo), more like Scratch extensions (asynchronous vs. synchronous), or some mix?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.