Support for pause/resume of game rendering loop (#476)

* added pause/resume

* don't override displaymode in game engine

* avoid setting light sensing display mode
This commit is contained in:
Peli de Halleux 2017-08-01 08:17:53 -07:00 committed by GitHub
parent 6a215478b0
commit 74799c65ac
9 changed files with 111 additions and 28 deletions

View File

@ -30,6 +30,8 @@ game.setScore(0);
```cards ```cards
game.startCountdown(10000); game.startCountdown(10000);
game.gameOver(); game.gameOver();
game.pause();
game.resume();
``` ```
### See also ### See also
@ -38,4 +40,5 @@ game.gameOver();
[ifOnEdgeBounce](/reference/game/if-on-edge-bounce), [get](/reference/game/get), [set](/reference/game/set), [ifOnEdgeBounce](/reference/game/if-on-edge-bounce), [get](/reference/game/get), [set](/reference/game/set),
[change](/reference/game/change), [isTouching](/reference/game/touching) [isTouchingEdge](/reference/game/touching-edge), [change](/reference/game/change), [isTouching](/reference/game/touching) [isTouchingEdge](/reference/game/touching-edge),
[addScore](/reference/game/change-score-by), [score](/reference/game/score), [setScore](/reference/game/set-score), [addScore](/reference/game/change-score-by), [score](/reference/game/score), [setScore](/reference/game/set-score),
[startCountdown](/reference/game/start-countdown), [gameOver](/reference/game/game-over) [startCountdown](/reference/game/start-countdown), [gameOver](/reference/game/game-over),
[pause](/reference/game/pause), [resume](/reference/game/resume)

View File

@ -0,0 +1,11 @@
# Pause
Pauses the game rendering engine to allow other animations on the screen.
```sig
game.pause()
```
### See Also
[resume](/reference/game/resume)

View File

@ -0,0 +1,11 @@
# Resume
Resumes the game rendering engine after a pause.
```sig
game.resume()
```
### See Also
[pause](/reference/game/pause)

View File

@ -81,12 +81,15 @@
"game.gameOver": "Displays a game over animation and the score.", "game.gameOver": "Displays a game over animation and the score.",
"game.invalidSprite": "Gets an invalid sprite; used to initialize locals.", "game.invalidSprite": "Gets an invalid sprite; used to initialize locals.",
"game.isGameOver": "Indicates if the game is display the game over sequence.", "game.isGameOver": "Indicates if the game is display the game over sequence.",
"game.isPaused": "Indicates if the game rendering is paused to allow other animations",
"game.isRunning": "Gets a value indicating if the game is still running. Returns `false` if game over.", "game.isRunning": "Gets a value indicating if the game is still running. Returns `false` if game over.",
"game.level": "Gets the current level", "game.level": "Gets the current level",
"game.levelUp": "Increments the level and display a message.", "game.levelUp": "Increments the level and display a message.",
"game.life": "Gets the current life", "game.life": "Gets the current life",
"game.pause": "Pauses the game rendering engine to allow other animations",
"game.removeLife": "Removes some life", "game.removeLife": "Removes some life",
"game.removeLife|param|life": "TODO", "game.removeLife|param|life": "TODO",
"game.resume": "Resumes the game rendering engine",
"game.score": "Gets the current score", "game.score": "Gets the current score",
"game.setLife": "Sets the current life value", "game.setLife": "Sets the current life value",
"game.setLife|param|value": "TODO", "game.setLife|param|value": "TODO",
@ -142,6 +145,7 @@
"input.temperature": "Gets the temperature in Celsius degrees (°C).", "input.temperature": "Gets the temperature in Celsius degrees (°C).",
"led": "Control of the LED screen.", "led": "Control of the LED screen.",
"led.brightness": "Get the screen brightness from 0 (off) to 255 (full bright).", "led.brightness": "Get the screen brightness from 0 (off) to 255 (full bright).",
"led.displayMode": "Gets the current display mode",
"led.enable": "Turns on or off the display", "led.enable": "Turns on or off the display",
"led.fadeIn": "Fades in the screen display.", "led.fadeIn": "Fades in the screen display.",
"led.fadeIn|param|ms": "TODO", "led.fadeIn|param|ms": "TODO",

View File

@ -236,6 +236,8 @@
"game.addScore|block": "change score by|%points", "game.addScore|block": "change score by|%points",
"game.createSprite|block": "create sprite at|x: %x|y: %y", "game.createSprite|block": "create sprite at|x: %x|y: %y",
"game.gameOver|block": "game over", "game.gameOver|block": "game over",
"game.pause|block": "pause",
"game.resume|block": "resume",
"game.score|block": "score", "game.score|block": "score",
"game.setScore|block": "set score %points", "game.setScore|block": "set score %points",
"game.startCountdown|block": "start countdown|(ms) %duration", "game.startCountdown|block": "start countdown|(ms) %duration",

View File

@ -32,8 +32,9 @@ namespace game {
let _countdownPause: number = 0; let _countdownPause: number = 0;
let _level: number = 1; let _level: number = 1;
let _gameId: number = 0; let _gameId: number = 0;
let img: Image; let _img: Image;
let sprites: LedSprite[]; let _sprites: LedSprite[];
let _paused: boolean = false;
/** /**
* Creates a new LED sprite pointing to the right. * Creates a new LED sprite pointing to the right.
@ -67,6 +68,7 @@ namespace game {
//% parts="ledmatrix" //% parts="ledmatrix"
export function addScore(points: number): void { export function addScore(points: number): void {
setScore(_score + points); setScore(_score + points);
if (!_paused)
control.inBackground(() => { control.inBackground(() => {
led.stopAnimation(); led.stopAnimation();
basic.showAnimation(`0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 1 1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 1 1 1 0 0 0 1 0 0 0 0 0 basic.showAnimation(`0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 1 1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 1 1 1 0 0 0 1 0 0 0 0 0
@ -94,6 +96,7 @@ namespace game {
_countdownPause = Math.max(500, ms); _countdownPause = Math.max(500, ms);
_startTime = -1; _startTime = -1;
_endTime = input.runningTime() + _countdownPause; _endTime = input.runningTime() + _countdownPause;
_paused = false;
control.inBackground(() => { control.inBackground(() => {
basic.pause(_countdownPause); basic.pause(_countdownPause);
gameOver(); gameOver();
@ -201,6 +204,7 @@ namespace game {
//% parts="ledmatrix" //% parts="ledmatrix"
export function removeLife(life: number): void { export function removeLife(life: number): void {
setLife(_life - life); setLife(_life - life);
if (!_paused)
control.inBackground(() => { control.inBackground(() => {
led.stopAnimation(); led.stopAnimation();
basic.showAnimation(`1 0 0 0 1 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 basic.showAnimation(`1 0 0 0 1 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0
@ -263,10 +267,38 @@ namespace game {
* Indicates if the game is display the game over sequence. * Indicates if the game is display the game over sequence.
*/ */
export function isGameOver(): boolean { export function isGameOver(): boolean {
let over: boolean;
return _isGameOver; return _isGameOver;
} }
/**
* Indicates if the game rendering is paused to allow other animations
*/
//%
export function isPaused(): boolean {
return _paused;
}
/**
* Pauses the game rendering engine to allow other animations
*/
//% blockId=game_pause block="pause"
//% advanced=true blockGap=8 help=game/pause
export function pause(): void {
plot()
_paused = true;
}
/**
* Resumes the game rendering engine
*/
//% blockId=game_resume block="resume"
//% advanced=true blockGap=8 help=game/resumeP
export function resume(): void {
_paused = false;
plot();
}
/** /**
* returns false if game can't start * returns false if game can't start
*/ */
@ -301,7 +333,7 @@ namespace game {
this._brightness = 255; this._brightness = 255;
this._enabled = true; this._enabled = true;
init(); init();
sprites.push(this); _sprites.push(this);
plot(); plot();
} }
@ -651,7 +683,7 @@ namespace game {
//% blockId="game_delete_sprite" block="delete %this" //% blockId="game_delete_sprite" block="delete %this"
public delete(): void { public delete(): void {
this._enabled = false; this._enabled = false;
if (sprites.removeElement(this)) if (_sprites.removeElement(this))
plot(); plot();
} }
@ -692,22 +724,21 @@ namespace game {
r = (now / ps._blink) % 2; r = (now / ps._blink) % 2;
} }
if (r == 0) { if (r == 0) {
img.setPixelBrightness(ps._x, ps._y, img.pixelBrightness(ps._x, ps._y) + ps._brightness); _img.setPixelBrightness(ps._x, ps._y, _img.pixelBrightness(ps._x, ps._y) + ps._brightness);
} }
} }
} }
} }
function init(): void { function init(): void {
if (img == null) { if (_img == null) {
img = images.createImage( _img = images.createImage(
`0 0 0 0 0 `0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0`); 0 0 0 0 0`);
sprites = (<LedSprite[]>[]); _sprites = (<LedSprite[]>[]);
led.setDisplayMode(DisplayMode.Greyscale);
basic.forever(() => { basic.forever(() => {
basic.pause(30); basic.pause(30);
plot(); plot();
@ -723,15 +754,18 @@ namespace game {
*/ */
//% parts="ledmatrix" //% parts="ledmatrix"
function plot(): void { function plot(): void {
if (game.isGameOver()) { if (game.isGameOver() || game.isPaused() || !_img) {
return; return;
} }
let now = input.runningTime(); let now = input.runningTime();
img.clear(); _img.clear();
for (let i = 0; i < sprites.length; i++) { for (let i = 0; i < _sprites.length; i++) {
sprites[i]._plot(now); _sprites[i]._plot(now);
} }
img.plotImage(0); const mode = led.displayMode() == DisplayMode.Greyscale ? DisplayMode.Greyscale : DisplayMode.BackAndWhite;
led.setDisplayMode(DisplayMode.Greyscale);
_img.plotImage(0);
led.setDisplayMode(mode);
} }
/** /**

View File

@ -96,6 +96,14 @@ namespace led {
uBit.display.setDisplayMode((DisplayMode)mode); uBit.display.setDisplayMode((DisplayMode)mode);
} }
/**
* Gets the current display mode
*/
//% weight=1 parts="ledmatrix" advanced=true
DisplayMode_ displayMode() {
return (DisplayMode_)uBit.display.getDisplayMode();
}
/** /**
* Turns on or off the display * Turns on or off the display
*/ */

View File

@ -509,6 +509,12 @@ declare namespace led {
//% parts="ledmatrix" advanced=true shim=led::setDisplayMode //% parts="ledmatrix" advanced=true shim=led::setDisplayMode
function setDisplayMode(mode: DisplayMode): void; function setDisplayMode(mode: DisplayMode): void;
/**
* Gets the current display mode
*/
//% weight=1 parts="ledmatrix" advanced=true shim=led::displayMode
function displayMode(): DisplayMode;
/** /**
* Turns on or off the display * Turns on or off the display
*/ */

View File

@ -305,6 +305,10 @@ namespace pxsim.led {
runtime.queueDisplayUpdate() runtime.queueDisplayUpdate()
} }
export function displayMode(): DisplayMode {
return board().ledMatrixState.displayMode;
}
export function screenshot(): Image { export function screenshot(): Image {
let img = createImage(5) let img = createImage(5)
board().ledMatrixState.image.copyTo(0, 5, img, 0); board().ledMatrixState.image.copyTo(0, 5, img, 0);