In the first chapter,we mentioned that Snake game includes two scenes - Menu and Game scene. This chapter will explain how to define scenes in Moscrif.
Menu scene
Menu scene is the first scene shown when game is started. This scene includes game buttons that manage Snake game. Buttons are instances of GameButton Class and are defined within GameButton.init method.
Once the user clicks on Game start menu, new instance of GameScene is created, MenuScene is hidden and GameScene shown.
Example of Menu scene:
include "app://core/constants.ms";
include "lib://game2d/scene.ms"; class MenuScene : Scene
{
function init()
{
super.init();
this._background = Bitmap.fromFile(M_MENU); this.bContinue = new SnakeButton({image:M_CONTINUE, pressedImage:M_CONTINUE_P});
this.bContinue.visible = false;
this.bContinue.x = (this.width - this.bContinue.width)/2;
this.bContinue.y = this.height / 2;
this.bContinue.onClick = function() { app.pop(); };
this.add(this.bContinue);
var bNewGameGyro = new SnakeButton({image:M_NEW_GAME_GYRO, pressedImage:M_NEW_GAME_GYRO_P});
bNewGameGyro.x = (this.width - bNewGameGyro.width)/2;
bNewGameGyro.y = this.bContinue.y + this.bContinue.height + M_VERTICAL_SPACE;
this.add(bNewGameGyro); var bNewGameTouch = new SnakeButton({image:M_NEW_GAME_TOUCH, pressedImage:M_NEW_GAME_TOUCH_P});
bNewGameTouch.x = (this.width - bNewGameTouch.width)/2;
bNewGameTouch.y = bNewGameGyro.y + bNewGameGyro.height + M_VERTICAL_SPACE;
bNewGameTouch.onClick = function()
{
app.gameScene = new GameScene();
app.push(app.gameScene);
this super.bContinue.visible = true;
}
this.add(bNewGameTouch); var bQuit = new SnakeButton({image:M_QUIT, pressedImage:M_QUIT_P});
bQuit.x = (this.width - bQuit.width)/2;
bQuit.y = bNewGameTouch.y + bNewGameTouch.height + M_VERTICAL_SPACE;
bQuit.onClick = :: app.quit();
this.add(bQuit);
} property width(v)
{
get return this._background.width;
} property height(v)
{
get return this._background.height;
} function showContinueBttn()
{
this.bContinue.visible = true;
} function draw(canvas)
{
canvas.drawBitmap(this._background, 0, 0);
super.draw(canvas);
}
}
Game scene
Game Scene creates characteristic of the Snake game. It includes all game objects, menu button, snake, food, clouds and scores. Game Scene includes game stages (levels) as well. Stages are defined in XML configuration file.
Example of the Game scene:
include "app://core/constants.ms";
include "app://core/simpleTimer.ms";
include "app://gui/score.ms";
include "app://gameObjects/snake/snake.ms";
include "app://gameObjects/foods/drop.ms";
include "app://gameObjects/foods/bigDrop.ms";
include "app://gameObjects/foods/strawberry.ms";
include "app://gameObjects/foods/clock.ms";
include "app://gameObjects/walls/leftWall.ms";
include "app://gameObjects/walls/rightWall.ms";
include "app://gameObjects/cloud.ms";
include "app://core/stage.ms";
class GameScene : Scene
{
//count - number of body parts
function init()
{
super.init(); this.actualStage = 1; var bMenu = new SnakeButton({image:G_MENU_BUTTON, pressedImage:G_MENU_BUTTON_P});
bMenu.onClick = function() {
var menuScene = new MenuScene();
menuScene.showContinueBttn();
app.push(menuScene);
};
this.add(bMenu); this._pushed = false; this.stage = new Stage();
this.stage.load(String.printf("stage%d.xml", this.actualStage));
this.speed_up = this.stage.speed_up; this.walls = new Array();
this.food = new Array();
this.clouds = new Array(); //Create clouds timer
this.cloudsTimer = new SimpleTimer(1000); /*** Load images ***/
//Background
this._background = Bitmap.fromFile(G_BACKGROUND); //Create walls
for (var y = 0; y < this.stage.area.length; y++) {
var left = true;
for (var x = 0; x < this.stage.area[y].length; x++) {
if (this.stage.area[y][x]) {
if (y - 1 > 0 && this.stage.area[y-1][x])
if (this.stage.area[y-1][x] instanceof LeftWall)
left = false;
else if (this.stage[y-1][x] instanceof RightWall)
left = true; var w = null
if (left)
w = new LeftWall();
else
w = new RightWall(); this.add(w)
left = !left; w.x = CELL_WIDTH * x;
w.y = CELL_HEIGHT * y;
this.stage.area[y][x] = w;
this.walls.push(w);
}
}
} //Create clocks
for (var i = 0; i < this.stage.clock_count; i++) {
var b = new Clock();
//Random position
var stop = false;
while (!stop) {
stop = true;
b.x = (1+rand(this.width/b.width-2))*b.width;
b.y = (1+rand(this.height/b.height-2))*b.height;
for (var i in this.food)
if (b.intersectsBounds(i))
stop = false;
for (var i in this.walls)
if (b.intersectsBounds(i))
stop = false;
} //Add object to the container
this.food.push(b);
this.add(b); } //Create strawberries
for (var i = 0; i < this.stage.strawberry_count; i++) {
var b = new Strawberry();
//Random position
var stop = false;
while (!stop) {
stop = true;
b.x = (1+rand(this.width/CELL_WIDTH-2))*CELL_WIDTH;
b.y = (1+rand(this.height/CELL_HEIGHT-2))*CELL_HEIGHT;
for (var i in this.food)
if (b.intersectsBounds(i))
stop = false;
for (var i in this.walls)
if (b.intersectsBounds(i))
stop = false;
} //Add object to the container
this.food.push(b);
this.add(b);
} //Create big drops
for (var i = 0; i < this.stage.big_drop_count; i++) {
var b = new BigDrop();
//Random position
var stop = false;
while (!stop) {
stop = true;
b.x = (1+rand(this.width/CELL_WIDTH-2))*CELL_WIDTH -10;
b.y = (1+rand(this.height/CELL_HEIGHT-2))*CELL_HEIGHT -10; for (var i in this.food)
if (b.intersectsBounds(i))
stop = false;
for (var i in this.walls)
if (b.intersectsBounds(i))
stop = false;
} //Add object to the container
this.food.push(b);
this.add(b);
} //Create drops
for (var i = 0; i < this.stage.drop_count; i++) {
var b = new Drop();
//Random position
var stop = false;
while (!stop) {
stop = true;
b.x = (1+rand(this.width/b.width-2))*b.width-10;
b.y = (1+rand(this.height/b.height-2))*b.height-10; for (var i in this.food)
if (b.intersectsBounds(i))
stop = false;
for (var i in this.walls)
if (b.intersectsBounds(i))
stop = false;
} //Add object to the container
this.food.push(b);
this.add(b);
} //Create Score
this.score = new Score();
this.score.right = this.width - 10; //Create Snake
this.snake = new Snake(this.stage.start_x, this.stage.start_y, this.stage.start_body_count, this.stage.start_direction);
this.snake.timer.sleep = this.stage.start_refresh;
} property x(v)
{
get return 0;
} property y(v)
{
get return 0;
} property width(v)
{
get return this._background.width;
} property height(v)
{
get return this._background.height;
} /**
* Set each variable to init state.
* @return nothing
*/
function restart()
{
this.snake.restart();
this.time = TIME;
} function endGame()
{
app.pop();
app.game = null;
app.menu.bContinue.visible = false;
} function winGame()
{
this.endGame();
} /**
* Function call at redrawing.
* @param canvas Canvas object.
* @return nothing
*/
function draw(canvas)
{
canvas.drawBitmap(this._background, 0, 0);
for (var i in this.walls)
i.draw(canvas);
for (var i in this.food)
i.draw(canvas);
this.snake.draw(canvas);
this.score.draw(canvas);
for (var i in this.clouds)
i.draw(canvas); super.draw(canvas);
} /**
* Function called each n millisecond. It defines property time.
* @return nothing
*/
function process()
{
var invalidate = this.score.onProcess();
for (var i in this.clouds) {
if (!i.onProcess(this))
this.clouds.removeByValue(i);
invalidate = true;
} if (this.snake.onProcess(this)) {
this._pushed = false;
invalidate = true;
} if (this.score.value >= this.stage.win_score)
this.winGame(); //Generate new clouds
if (this.cloudsTimer.onProcess()) {
if (rand(100) < this.stage.cloudiness) {
var cloud = new Cloud()
cloud.direction = this.stage.clouds_direction;
cloud.speed = this.stage.clouds_speed;
if (this.stage.clouds_direction > 0 && this.stage.clouds_direction < Math.PI) {
if (rand(2)) {
cloud.x = rand(this.width + cloud.width) - cloud.width;
cloud.y = -cloud.height;
}
else {
cloud.x = -cloud.width;
cloud.y = rand(this.height + cloud.height) - cloud.height;
}
}
else {
if (rand(2)) {
cloud.x = rand(this.width + cloud.width) - cloud.width;
cloud.y = this.height;
}
else {
cloud.x = this.width;
cloud.y = rand(this.height + cloud.height) - cloud.height;
}
}
this.clouds.push(cloud);
}
} if (invalidate)
return true;
else
return false;
} function pointerPressed(x,y)
{
if (super.pointerPressed(x,y))
return; if (this._pushed == false) {
this._pushed = true;
this.snake.turn(x,y);
}
}
}
|