Tuesday, August 14, 2012

Creating a Pentomino game using AS3: Part 27

In this part we will draw level previews for each level item in the Saved Levels browser.

Go to saved_levels.as and find the goPage() function. In the 3 if...statements that handle level item appearance add lines that call drawPreview() function and pass 2 values - levelPreview MovieClip of the respective item (item1, item2 or item3) and the map grid data.

private function goPage(pageNum:int):void {
currentPage = pageNum;
tPage.text = "Page " + currentPage + "/" + pages;

// level items
item1.alpha = item2.alpha = item3.alpha = 0;
item1.mouseEnabled = item2.mouseEnabled = item3.mouseEnabled = false;
item1.mouseChildren = item2.mouseChildren = item3.mouseChildren = false;


if (levels[3 * (currentPage-1)] != null) {
item1.alpha = 1;
item1.mouseEnabled = true;
item1.mouseChildren = true;
item1.tTitle.text = levels[3 * (currentPage-1)].name;
countShapes(item1, levels[3 * (currentPage-1)].shapes);
drawPreview(item1.levelPreview, levels[3 * (currentPage-1)].grid);
}

if (levels[3 * (currentPage-1)+1] != null) {
item2.alpha = 1;
item2.mouseEnabled = true;
item2.mouseChildren = true;
item2.tTitle.text = levels[3 * (currentPage-1) + 1].name;
countShapes(item2, levels[3 * (currentPage-1) + 1].shapes);
drawPreview(item2.levelPreview, levels[3 * (currentPage-1) + 1].grid);
}

if (levels[3 * (currentPage-1)+2] != null) {
item3.alpha = 1;
item3.mouseEnabled = true;
item3.mouseChildren = true;
item3.tTitle.text = levels[3 * (currentPage-1) + 2].name;
countShapes(item3, levels[3 * (currentPage-1) + 2].shapes);
drawPreview(item3.levelPreview, levels[3 * (currentPage-1) + 2].grid);
}

// page navigation
btn_previous.alpha = btn_next.alpha = 0;
btn_previous.mouseEnabled = btn_next.mouseEnabled = false;

if (currentPage > 1) {
btn_previous.alpha = 1;
btn_previous.mouseEnabled = true;
}

if (currentPage < pages) {
btn_next.alpha = 1;
btn_next.mouseEnabled = true;
}
}

Open your project in Flash and open the levelPreview MovieClip. Set its contents to a rectangle if you haven't already. Add a new empty MovieClip inside, give it an id "shape".

Now we can return to saved_levels.as and write the drawPreview() function.

The function will combine some of the modified code from calculateGrid() and drawGrid() functions from pentomino_game.as.

Firstly we declare these variables:

var columns:int = mapGrid[0].length;
var rows:int = mapGrid.length;
var frameWidth:int = levelPreview.width;
var frameHeight:int = levelPreview.height;
var padding:int = 5;
var fitWidth:int = levelPreview.width - (padding * 2);
var fitHeight:int = levelPreview.height - (padding * 2);
var gridStartX:int;
var gridStartY:int;

// calculate width of a cell:
var gridCellWidth:int = Math.round(fitWidth / columns);

var width:int = columns * gridCellWidth;
var height:int = rows * gridCellWidth;

You can see that we use the width and height of the levelPreview MovieClip to calculate where to fit the map.

After gridCellWidth is calculated, we can find out how to position the map (the X and Y coordinates of "shape"):

// calculate side margin
gridStartX = (frameWidth - width) / 2;

if (height < fitHeight) {
gridStartY = (fitHeight - height) / 2;
}
if (height >= fitHeight) {
gridCellWidth = Math.round(fitHeight / rows);
height = rows * gridCellWidth;
width = columns * gridCellWidth;
gridStartY = (frameHeight - height) / 2;
gridStartX = (frameWidth - width) / 2;
}

Then, after positioning the shape, we clear its graphics and draw the map using a loop. Use a function drawCell() to draw each cell. However, instead of passing just 5 values to the function as we did in pentomino_game and pentomino_editor, we're going to add 2 more values - gridCellWidth and levelPreview.shape:

// draw map
levelPreview.shape.x = gridStartX;
levelPreview.shape.y = gridStartY;
levelPreview.shape.graphics.clear();
var i:int;
var u:int;

for (i = 0; i < rows; i++) {
for (u = 0; u < columns; u++) {
if (mapGrid[i][u] == 1) drawCell(u, i, 0xffffff, 1, 0x999999, gridCellWidth, levelPreview.shape);
}
}

The function draws the map:

private function drawCell(width:int, height:int, fill:uint, thick:Number, line:uint, gridCellWidth:int, gridShape:MovieClip):void {
gridShape.graphics.beginFill(fill);
gridShape.graphics.lineStyle(thick, line);
gridShape.graphics.drawRect(width * gridCellWidth, height * gridCellWidth, gridCellWidth, gridCellWidth);
}

Full saved_levels.as so far:

package  
{
import flash.display.MovieClip;
import flash.display.Shape;
import flash.events.MouseEvent;
import flash.net.SharedObject;

/**
 * Open-source pentomino game engine
 * @author Kirill Poletaev
 */

public class saved_levels extends MovieClip
{
private var savedLevels:SharedObject;
private var levels:Array = [];
private var pages:int;
private var currentPage:int;

public function saved_levels() 
{
savedLevels = SharedObject.getLocal("myLevels");
btn_back.addEventListener(MouseEvent.CLICK, doBack);
if (savedLevels.data.levels != null) levels = savedLevels.data.levels;
tInfo.text = levels.length + " levels (" + savedLevels.size + "B)";
pages = Math.floor(levels.length / 3) + 1;
goPage(1);
btn_previous.addEventListener(MouseEvent.CLICK, function() { goPage(currentPage - 1) } );
btn_next.addEventListener(MouseEvent.CLICK, function() { goPage(currentPage + 1) } );
}

private function goPage(pageNum:int):void {
currentPage = pageNum;
tPage.text = "Page " + currentPage + "/" + pages;

// level items
item1.alpha = item2.alpha = item3.alpha = 0;
item1.mouseEnabled = item2.mouseEnabled = item3.mouseEnabled = false;
item1.mouseChildren = item2.mouseChildren = item3.mouseChildren = false;


if (levels[3 * (currentPage-1)] != null) {
item1.alpha = 1;
item1.mouseEnabled = true;
item1.mouseChildren = true;
item1.tTitle.text = levels[3 * (currentPage-1)].name;
countShapes(item1, levels[3 * (currentPage-1)].shapes);
drawPreview(item1.levelPreview, levels[3 * (currentPage-1)].grid);
}

if (levels[3 * (currentPage-1)+1] != null) {
item2.alpha = 1;
item2.mouseEnabled = true;
item2.mouseChildren = true;
item2.tTitle.text = levels[3 * (currentPage-1) + 1].name;
countShapes(item2, levels[3 * (currentPage-1) + 1].shapes);
drawPreview(item2.levelPreview, levels[3 * (currentPage-1) + 1].grid);
}

if (levels[3 * (currentPage-1)+2] != null) {
item3.alpha = 1;
item3.mouseEnabled = true;
item3.mouseChildren = true;
item3.tTitle.text = levels[3 * (currentPage-1) + 2].name;
countShapes(item3, levels[3 * (currentPage-1) + 2].shapes);
drawPreview(item3.levelPreview, levels[3 * (currentPage-1) + 2].grid);
}

// page navigation
btn_previous.alpha = btn_next.alpha = 0;
btn_previous.mouseEnabled = btn_next.mouseEnabled = false;

if (currentPage > 1) {
btn_previous.alpha = 1;
btn_previous.mouseEnabled = true;
}

if (currentPage < pages) {
btn_next.alpha = 1;
btn_next.mouseEnabled = true;
}
}

private function countShapes(levelItem:MovieClip, shapes:Array):void {
for (var i:int = 1; i <= 12; i++) {
levelItem["tShape" + i].text = shapes[i - 1];
}
}

private function drawPreview(levelPreview:MovieClip, mapGrid:Array):void {
var columns:int = mapGrid[0].length;
var rows:int = mapGrid.length;
var frameWidth:int = levelPreview.width;
var frameHeight:int = levelPreview.height;
var padding:int = 5;
var fitWidth:int = levelPreview.width - (padding * 2);
var fitHeight:int = levelPreview.height - (padding * 2);
var gridStartX:int;
var gridStartY:int;

// calculate width of a cell:
var gridCellWidth:int = Math.round(fitWidth / columns);

var width:int = columns * gridCellWidth;
var height:int = rows * gridCellWidth;

// calculate side margin
gridStartX = (frameWidth - width) / 2;

if (height < fitHeight) {
gridStartY = (fitHeight - height) / 2;
}
if (height >= fitHeight) {
gridCellWidth = Math.round(fitHeight / rows);
height = rows * gridCellWidth;
width = columns * gridCellWidth;
gridStartY = (frameHeight - height) / 2;
gridStartX = (frameWidth - width) / 2;
}

// draw map
levelPreview.shape.x = gridStartX;
levelPreview.shape.y = gridStartY;
levelPreview.shape.graphics.clear();
var i:int;
var u:int;

for (i = 0; i < rows; i++) {
for (u = 0; u < columns; u++) {
if (mapGrid[i][u] == 1) drawCell(u, i, 0xffffff, 1, 0x999999, gridCellWidth, levelPreview.shape);
}
}
}

private function drawCell(width:int, height:int, fill:uint, thick:Number, line:uint, gridCellWidth:int, gridShape:MovieClip):void {
gridShape.graphics.beginFill(fill);
gridShape.graphics.lineStyle(thick, line);
gridShape.graphics.drawRect(width * gridCellWidth, height * gridCellWidth, gridCellWidth, gridCellWidth);
}

private function doBack(evt:MouseEvent):void {
(root as MovieClip).gotoAndStop(1);
}
}

}

Thanks for reading!

Results:


No comments:

Post a Comment