PixelTetris
左右移動 : ←, → or a, d
* 落下加速 : ↓ or s
* 即時落下 : ↑ or w
* 右回転 : z or Ctrl
* 左回転 : x or Shift
/**
* Copyright poiasd ( http://wonderfl.net/user/poiasd )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/t09M
*/
/**
* 左右移動 : ←, → or a, d
* 落下加速 : ↓ or s
* 即時落下 : ↑ or w
* 右回転 : z or Ctrl
* 左回転 : x or Shift
*/
package {
import flash.display.BitmapData;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.KeyboardEvent;
import flash.events.MouseEvent;
import flash.geom.Rectangle;
[SWF (width = "465", height = "465", frameRate = "60", backgroundColor = "0xFFFFFF")]
public class Main extends Sprite {
private const _WIDTH:uint = 10;
private const _HEIGHT:uint = 20;
private var _isPlaying:Boolean;
private var _keyState:uint;
private var _canvas:BitmapData;
private var _canvasRect:Rectangle;
private var _tetrimino:Tetrimino;
private var _field:Array;
private var _block:Object;
private var _nextList:Array;
private var _speed:uint = 60;
public function Main() {
_init();
}
private function _init():void {
Wonderfl.capture_delay(20);
stage.scaleMode = "noScale";
stage.align = "LT";
graphics.beginFill(0x8090A0);
graphics.drawRect(0, 0, stage.stageWidth, stage.stageHeight);
graphics.endFill();
_canvas = new BitmapData(_WIDTH, _HEIGHT, true, 0xFFFFFF);
addChild(new PixelDisplay(stage, _canvas));
_canvasRect = _canvas.rect;
_tetrimino = new Tetrimino();
_field = new Array(_HEIGHT + 1).map(function(...args):Array {return new Array(_WIDTH);});
_block = {type:0, angle:0, x:0, y:0};
_keyListener();
addEventListener(Event.ENTER_FRAME, _enterFrameHandler);
_start();
}
private var _prevKey:uint = 0;
private var _count:int = 0;
private var _wait:int = 0;
private function _enterFrameHandler(event:Event):void {
if (!_isPlaying) return;
//左右キー
if (_keyState & 1) {
if (_wait == 0) {
_moveBlock(-1, 0);
_wait = 12 - (_prevKey & 1) * 10;
} else {
_wait--;
}
} else if ((_keyState >> 2) & 1) {
if (_wait == 0) {
_moveBlock(1, 0);
_wait = 12 - ((_prevKey >> 2) & 1) * 10;
} else {
_wait--;
}
} else {
_wait = 0;
}
//下キー
if ((_keyState >> 3) & 1) {
_speed = 2;
} else {
_speed = 60;
}
//上キー
if (((_keyState >> 1) & 1) > ((_prevKey >> 1) & 1)) {
while (_moveBlock(0, 1)) {};
_count = _speed;
}
//回転キー
if (((_keyState >> 4) & 1) > ((_prevKey >> 4) & 1)) {
_rotateBlock(true);
}
if (((_keyState >> 5) & 1) > ((_prevKey >> 5) & 1)) {
_rotateBlock(false);
}
_prevKey = _keyState;
if (_count >= _speed) {
if (!_moveBlock(0, 1)) _deleteLine();
_count = 0;
} else {
_count++;
}
_draw();
}
private function _draw():void {
_canvas.lock();
_canvas.fillRect(_canvasRect, 0x20000000);
var colorList:Array = _tetrimino.colorList;
for (var y:int = 0; y < _HEIGHT; y++) {
for (var x:int = 0; x < _WIDTH; x++) {
var type:int = _field[y + 1][x] - 1;
if (type >= 0) _canvas.setPixel32(x, y, 0xC0000000 + colorList[type]);
}
}
_canvas.unlock();
}
private function _initBlock():void {
if (_nextList.length == 0) {
_nextList = [0, 1, 2, 3, 4, 5, 6];
_nextList.sort(function():int {return int(Math.random() * 3) - 1;});
}
_block.type = _nextList[0];
_block.angle = 0;
var w:int = _tetrimino.getBlock(_block.type, _block.angle).length;
_block.x = Math.round ((_WIDTH - w) * 0.5);
_block.y = 0;
_nextList = _nextList.slice(1);
if (_checkSpace()){
_rewriteField(true);
} else {
_gameOver();
}
}
private function _moveBlock(moveX:int, moveY:int):Boolean {
if (moveX == 0 && moveY == 0) return false;
_rewriteField(false);
_block.x += moveX;
_block.y += moveY;
if (_checkSpace()) {
_rewriteField(true);
return true;
}
_block.x -= moveX;
_block.y -= moveY;
_rewriteField(true);
return false;
}
private function _rotateBlock(cw:Boolean):void {
_rewriteField(false);
var angle:int = _block.angle;
_block.angle = (cw ? angle + 1 : angle + 3) % 4;
if (!_checkSpace()) _block.angle = angle;
_rewriteField(true);
}
private function _checkSpace():Boolean {
var block:Array = _tetrimino.getBlock(_block.type, _block.angle);
var bx:int = _block.x;
var by:int = _block.y;
var len:int = block.length;
for (var y:int = 0; y < len; y++) {
for (var x:int = 0; x < len; x++) {
if (block[y][x]) {
if (bx + x < 0 || bx + x >= _WIDTH || by + y >= _HEIGHT + 1) {
return false;
} else if (_field[by + y][bx + x]) {
return false;
}
}
}
}
return true;
}
private function _rewriteField(ew:Boolean):void {
var block:Array = _tetrimino.getBlock(_block.type, _block.angle);
var bx:int = _block.x;
var by:int = _block.y;
var len:int = block.length;
for (var y:int = 0; y < len; y++) {
for (var x:int = 0; x < len; x++) {
if (block[y][x]) _field[by + y][bx + x] = ew ? block[y][x] : 0;
}
}
}
private function _deleteLine():void {
var list:Array = [];
for (var y:int = 1; y < _HEIGHT + 1; y++) {
if (_field[y].indexOf(0) == -1) list.push(y);
}
if (list.length == 0) {
_initBlock();
return;
}
var frame:int = _WIDTH;
addEventListener(Event.ENTER_FRAME, animation);
_stop();
function animation(event:Event):void {
if (frame > 0) {
_canvas.lock();
for each (y in list) {
_canvas.setPixel32(frame - 1, y - 1, 0x20000000);
}
_canvas.unlock();
} else if (frame < -8) {
for each (y in list) {
_field.splice(y, 1);
_field.unshift(new Array(_WIDTH).map(function():int {return 0;}));
}
removeEventListener(Event.ENTER_FRAME, animation);
_initBlock();
_play();
}
frame--;
}
}
private function _gameOver():void {
var frame:int = _HEIGHT << 1;
addEventListener(Event.ENTER_FRAME, animation);
function animation(event:Event):void {
if (frame > 0) {
if (frame % 2 == 0) {
var y:int = frame >> 1;
_canvas.lock();
for (var x:int = 0; x < _WIDTH; x++) {
if (_field [y][x]) _canvas.setPixel32(x, y - 1, 0xC0303030);
}
_canvas.unlock();
}
} else {
removeEventListener(Event.ENTER_FRAME, animation);
stage.addEventListener(MouseEvent.MOUSE_DOWN, function(e:MouseEvent):void {
_start();
stage.removeEventListener(MouseEvent.MOUSE_DOWN, arguments.callee);
});
}
frame--;
}
_stop();
}
private function _start():void {
for (var y:int = 0; y < _HEIGHT + 1; y++) {
for (var x:int = 0; x < _WIDTH; x++) {
_field[y][x] = 0;
}
}
_nextList = [];
_initBlock();
_play();
}
private function _play():void {
_isPlaying = true;
}
private function _stop():void {
_isPlaying = false;
}
private function _keyListener():void {
var list1:Array = [37, 38, 39, 40, 90, 88]; //←,↑,→,↓,z,x
var list2:Array = [65, 87, 68, 83, 17, 16]; //a,w,d,s,Ctrl,Shift
var key:Object = {};
for (var i:int = 0; i < list1.length; i++) {
key[list1[i]] = i;
key[list2[i]] = i;
}
stage.addEventListener(KeyboardEvent.KEY_DOWN, function(e:KeyboardEvent):void {
if (key[e.keyCode] != undefined) _keyState |= 1 << key[e.keyCode];
});
stage.addEventListener(KeyboardEvent.KEY_UP, function(e:KeyboardEvent):void {
if (key[e.keyCode] != undefined) _keyState &= ~(1 << key[e.keyCode]);
});
}
}
}
class Tetrimino {
private var _colorList:Array;
private var _blockList:Array;
public function Tetrimino() {
_colorList = [0x00FFFF, 0x0000FF, 0xFF9900, 0xFFFF00, 0xFF0000, 0xFF00FF, 0x00FF00];
_blockList = [];
var list:Array = ["410111213", "310110212", "300101112", "200100111", "300011112", "310011112", "310011102"];
for (var i:int = 0; i < list.length; i++) {
_blockList[i] = _createBlock(list[i], i);
}
}
public function get colorList():Array {
return _colorList;
}
public function getBlock(type:uint, angle:uint):Array {
return _blockList[type][angle];
}
private function _createBlock(str:String, type:uint):Array {
var rotates:Array = [];
var block:Array = str.split("");
var size:int = block[0];
for (var i:int = 0; i < 4; i++) {
rotates[i] = [];
for (var y:int = 0; y < size; y++) {
rotates[i][y] = [];
for (var x:int = 0; x < size; x++) {
rotates[i][y][x] = 0;
}
}
for (var j:int = 1; j < block.length; j++) {
var temp:int = block[j];
x = block[j] = size - 1 - block[++j];
y = block[j] = temp;
rotates[i][y][x] = type + 1;
}
}
return rotates;
}
}
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Sprite;
import flash.display.Stage;
import flash.events.MouseEvent;
import com.bit101.components.*;
class PixelDisplay extends Sprite {
private var _stageWidth:uint;
private var _stageHeight:uint;
private var _rate:int;
private var _bmp:Bitmap;
private var _label:Label;
public function PixelDisplay(stage:Stage, canvas:BitmapData) {
_stageWidth = stage.stageWidth;
_stageHeight = stage.stageHeight;
_bmp = addChild(new Bitmap(canvas)) as Bitmap;
_bmp.x = _stageWidth - _bmp.width >> 1;
_bmp.y = _stageHeight - _bmp.height >> 1;
_rate = 1;
var panel:Panel = new Panel(this, _stageWidth - 100, 2);
panel.width = 98;
panel.height = 26;
var plus:PushButton = new PushButton(this, _stageWidth - 50, 5, "+", _zoomIn);
plus.width = 20;
var minus:PushButton = new PushButton(this, _stageWidth - 25, 5, "-", _zoomOut);
minus.width = 20;
_label = new Label(this, _stageWidth - 89, 5, "100 %");
}
public function get canvas():BitmapData {
return _bmp.bitmapData;
}
public function set canvas(canvas:BitmapData):void {
_bmp.bitmapData = canvas;
}
private function _zoomIn(event:MouseEvent):void {
if (_bmp.width * 2 < _stageWidth && _bmp.height * 2 < _stageHeight) {
_rate *= 2;
_bmp.scaleX = _rate;
_bmp.scaleY = _rate;
_bmp.x = _stageWidth - _bmp.width >> 1;
_bmp.y = _stageHeight - _bmp.height >> 1;
_label.text = _rate * 100 + " %";
_label.draw();
_label.x = _stageWidth - 74 - _label.width * 0.5;
}
}
private function _zoomOut(event:MouseEvent):void {
if (_rate > 1) {
_rate *= 0.5;
_bmp.scaleX = _rate;
_bmp.scaleY = _rate;
_bmp.x = _stageWidth - _bmp.width >> 1;
_bmp.y = _stageHeight - _bmp.height >> 1;
_label.text = _rate * 100 + " %";
_label.draw();
_label.x = _stageWidth - 74 - _label.width * 0.5;
}
}
}