2.1.28, initiation update to PXT v5.28.24 (#54)

This commit is contained in:
Amerlander
2019-12-02 05:58:26 +01:00
committed by Peli de Halleux
parent 38a964516e
commit 5c114a0c57
1261 changed files with 50692 additions and 21604 deletions

View File

@ -0,0 +1,14 @@
# Eddystone Beacon
```blocks
led.enable(false)
bluetooth.advertiseUrl(
"https://calliope.cc",
7,
false
)
```
```package
device
```

View File

@ -0,0 +1,31 @@
# Egg and Spoon race
The [Egg and Spoon](https://en.wikipedia.org/wiki/Egg-and-spoon_race) race is a game where a player carries an object (like an egg) across some distance without it falling out of a holder. In the case of the Egg and Spoon, the player must carefully walk with an egg held in a spoon. The egg must remain in the spoon until the player crosses the finish line. The egg can easily roll out of the spoon so the player needs skill and patience to balance the egg until finishing the race.
You can program your @boardname@ to be an egg and let your hand be the spoon. If you walk too fast or waver in holding the @boardname@, you might "drop the egg!". Try to keep the balance point in the center of the screen.
```blocks
let accY = 0
let accX = 0
let y = 0
let x = 0
basic.forever(() => {
led.plot(x, y)
accX = input.acceleration(Dimension.X)
accY = input.acceleration(Dimension.Y)
if (accX < -150 && x > 0) {
x += -1
} else if (accX > 150 && x < 4) {
x += 1
}
if (accY < -150 && y > 0) {
y += -1
} else if (accY > 150 && y < 4) {
y += 1
}
basic.pause(500)
basic.clearScreen()
})
x = 2
y = 2
```

142
docs/examples/gameofLife.md Normal file
View File

@ -0,0 +1,142 @@
# Game of Life
The [Game of Life](https://en.wikipedia.org/wiki/Conway%27s_Game_of_Life) simulates life in a grid world (a two-dimensional block of cells). The cells in the grid have a state of "alive" or "dead". The game starts with a population of cells placed in a certain pattern on the grid. A simulation is run, and based on some simple rules for life and death, cells continue to live, die off, or reproduce.
## Rules for Life
The rules for life in the grid are:
1. A living cell with less than two live cells next to it will die. This is underpopulation, no social support.
2. A living cell with two or three live cells next to it continues to live. This is a healthy population.
3. A living cell with more than three live cells next to it will die. This is over overpopulation, scarce resources.
4. A dead cell with three live cells next to it turns into a living cell. This is reproduction.
Depending on the pattern of living cells at the start of the game, some population simulations may survive longer than others.
## Game of Life simulation in LEDs
Here's a program that simulates cell life in the LED matrix. Use button ``A`` for the next stage of life and button ``B`` to reset.
```typescript
//https://en.wikipedia.org/wiki/Conway%27s_Game_of_Life
let lifeChart: Image = null
//Use button A for the next iteration of game of life
input.onButtonPressed(Button.A, () => {
gameOfLife();
show();
})
//Use button B for reseting to random initial seed state
input.onButtonPressed(Button.B, () => {
reset();
show();
})
lifeChart = images.createImage(`
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
`)
//State holds the information about pixel is live or dead
//false means dead, true means live.
let state = [false, false, false, false, false,
false, false, false, false, false,
false, false, false, false, false,
false, false, false, false, false,
false, false, false, false, false]
//get & set on any array
function getState(arr: boolean[], x: number, y: number): boolean {
return arr[x * 5 + y];
}
function setState(arr: boolean[], x: number, y: number, value: boolean): void {
arr[x * 5 + y] = value;
}
//Generate random initial state.
function reset() {
for (let x = 0; x < 5; x++) {
for (let y = 0; y < 5; y++) {
setState(state, x, y, Math.randomBoolean());
}
}
}
//Show the lifeChart based on the state
function show() {
for (let x = 0; x < 5; x++) {
for (let y = 0; y < 5; y++) {
lifeChart.setPixel(x, y, getState(state, x, y));
}
}
lifeChart.plotImage(0);
}
//Core function
function gameOfLife() {
let result: boolean[] = [];
let count = 0;
for (let x = 0; x < 5; x++) {
for (let y = 0; y < 5; y++) {
count = 0;
//Count the live cells in the next row
if ((x + 1) < 5) {
if (getState(state, x + 1, y)) {
count++;
}
if ((y + 1 < 5) && getState(state, x + 1, y + 1)) {
count++;
}
if ((y - 1 >= 0) && getState(state, x + 1, y - 1)) {
count++;
}
}
//Count the live cells in the previous row
if ((x - 1) >= 0) {
if (getState(state, x - 1, y)) {
count++;
}
if ((y + 1 < 5) && getState(state, x - 1, y + 1)) {
count++;
}
if ((y - 1 >= 0) && getState(state, x - 1, y - 1)) {
count++;
}
}
//Count the live cells in the current row exlcuding the current position.
if ((y - 1 >= 0) && getState(state, x, y - 1)) {
count++;
}
if ((y + 1 < 5) && getState(state, x, y + 1)) {
count++;
}
// Toggle live / dead cells based on the neighbour count.
// Any live cell with fewer than two live neighbours dies, as if caused by underpopulation.
// Any live cell with two or three live neighbours lives on to the next generation.
// Any dead cell with exactly three live neighbours becomes a live cell, as if by reproduction.
// Any live cell with more than three live neighbours dies, as if by overpopulation.
switch (count) {
case 0: setState(result, x, y, false); break;
case 1: setState(result, x, y, false); break;
case 2: setState(result, x, y, getState(state, x, y)); break;
case 3: setState(result, x, y, true); break;
default: setState(result, x, y, false); break;
}
}
}
//Update the state
state = result;
}
//Initial reset & show
reset();
show();
```

View File

@ -0,0 +1,104 @@
# Pi Monte Carlo
Approximate the value of **pi** using your @boardname@!
## Thinking about it...
Ok, let's pretend that a circle fits inside a square where the edge of the circle touches the sides of the square. If we say that the radius, called ``r``, of circle is `1` then the length of each side of the square is `2`, or ``2 * r``. The area of the circle is ``pi * (r ** 2)`` and the area of the square then is ``(r * 2) ** 2``. We don't know what ``pi`` is so we can arrange a relationship between the area of the circle and the area of the square to solve for the value of ``pi``.
### Circle and square
An interesting relationship between the circle and the square is that the area of the circle divided by the area of the square is:
``area ratio = (pi * (r ** 2)) / ((r * 2) ** 2) = pi / 4``
Well, we can see that if we knew the area of both the circle and the square we could find out what the value of ``pi`` is! It's simply this:
```
pi = (area of circle) / (area of square) * 4
```
so then...
```
area ratio = (area of circle) / (area of square)
pi = (area ratio) * 4
```
One problem though. We know the area of the square, sure enough it's `4`, but what's the area of the circle?
That's the dilemma! We need to know the area of the circle to find out what ``pi`` is and we need the value of ``pi`` the find the area of the circle!
### Dots, lots of dots
What if we had a lot of really small dots that we could fill into the circle and into the parts of the square that the circle didn't cover. We'll try to cover the area of both shapes with as many dots as possible.
If we count the number of dots placed in both the circle and the square, we could find the ``area ratio`` between the two shapes. And, in the equation shown above, we can discover ``pi`` if we have this ratio. The ``area ratio`` is:
``area ratio = (dots in circle) / ((dots in circle) + (dots only in square))``
Of course, we can't completely fill the area of both shapes with dots but we could get enough of them in there to give a useful ratio between the circle and the square.
### Making and counting dots
To make the "dots" we can randomly make a value and see if it would fit as a coordinate within the shape we're trying to fill. If it fits, increase the count of dots and try to make more for some amount of time. The more dots created, the better the accuracy of our value for ``area ratio``.
### Monte Carlo method
This method of filling coordinate points, counting them, and using the difference or ratio of the counts is called the _Monte Carlo_ method or approximation.
## Monte Carlo approximation of _pi_
```blocks
let pir = 0
let pid = 0
let y = 0
let pin = 0
let x = 0
let r2 = 0
let r = 0
let inside = 0
let n = 0
// A simple Monte-Carlo simulation to approximate Pi.
//
// number of points
n = 1000000
//
// radius of the circle
r = 4000
//
// radius square
r2 = r * r
//
basic.forever(() => {
inside = 0
for (let i = 0; i < n; i++) {
// generate a point within the square
x = Math.randomRange(0, r + 1)
y = Math.randomRange(0, r + 1)
// test if the point is within the circle
// sqrt(x**2 + y**2) < r ==> x**2 + y**2 < r**2
if (x * x + y * y < r2) {
inside += 1
}
}
// surface of a square: 4 * r * r surface of a circle:
// r * r * pi => inside / n ~= (r*r*pi) / (4*r*r) ~=
// pi / 4 pi = inside / n * 4
//
pin = inside * 4
// only integer arithmetic here...
pid = pin / n
pir = pin % n
// show results
basic.showLeds(`
# # # # #
. # . # .
. # . # .
. # . # .
. # . . #
`)
basic.showString(" " + pid + "." + pir)
})
```

View File

@ -0,0 +1,12 @@
# Plot Acceleration
Plot acceleration in the ``x`` dimension on the LEDs.
```blocks
basic.forever(() => {
led.plotBarGraph(
input.acceleration(Dimension.X),
1023
)
})
```

View File

@ -0,0 +1,12 @@
# Plot Light level
Show the current light level as a bar graph.
```blocks
basic.forever(() => {
led.plotBarGraph(
input.lightLevel(),
255
)
})
```

View File

@ -0,0 +1,90 @@
# Radio Dashboard
```typescript
/**
* Radio monitoring dashboard
*
* Each radio client is represented by a dot on the screen.
* Once a client is registered, it will stay at the same pixel location
* forever.
*
* Radio clients can simply send a number (between 0..255) on group 4.
* They must transmit the serial number using ``radio.setTransmitSerialNumber(true)``
*
* The received number is used to set the LED brightness for that client.
*
* If the radio packet is not received for 10sec, the LED starts blinking.
*/
const deadPing = 20000;
const lostPing = 10000;
interface Client {
// client serial id
id: number;
// sprite on screen
sprite: game.LedSprite;
// last ping received
ping: number;
}
const clients: Client[] = [];
/* lazy allocate sprite */
function getClient(id: number): Client {
// needs an id to track radio client's identity
if (!id)
return undefined;
// look for cached clients
for (const client of clients)
if (client.id == id)
return client;
const n = clients.length;
if (n == 24) // out of pixels
return undefined;
const client: Client = {
id: id,
sprite: game.createSprite(n % 5, n / 5),
ping: input.runningTime()
}
clients.push(client);
return client;
}
// store data received by clients
radio.onReceivedNumber(function (receivedNumber) {
const serialNumber = radio.receivedPacket(RadioPacketProperty.SerialNumber)
const client = getClient(serialNumber);
if (!client)
return;
client.ping = input.runningTime()
client.sprite.setBrightness(Math.max(1, receivedNumber & 0xff));
})
// monitor the sprites and start blinking when no packet is received
basic.forever(() => {
const now = input.runningTime()
for (const client of clients) {
// lost signal starts blinking
const lastPing = now - client.ping;
if (lastPing > deadPing) {
client.sprite.setBlink(0)
client.sprite.setBrightness(0)
}
else if (lastPing > lostPing)
client.sprite.setBlink(500);
else
client.sprite.setBlink(0);
}
basic.pause(500)
})
// setup the radio and start!
radio.setGroup(4)
game.addScore(1)
```
```package
radio
```

9
docs/examples/rando.md Normal file
View File

@ -0,0 +1,9 @@
# Rando
Generate a random coordinate and display it on the LED screen.
```blocks
basic.forever(() => {
led.toggle(Math.randomRange(0, 5), Math.randomRange(0, 5))
})
```