ZSTetris
Z, Sが交互に落ちてきます
160 blocks まではいけた
// forked from yambian's ZSTetris
// forked from motioneditor's forked from: forked from: forked from: 普通のテトリス - Tetris
// forked from motioneditor's forked from: forked from: 普通のテトリス - Tetris
// forked from kanariia's forked from: 普通のテトリス - Tetris
// forked from rsakane's 普通のテトリス - Tetris
// Z, Sが交互に落ちてきます
// 160 bblocks まではいけた
package
{
/*
* 参考サイト - http://www.nhk.or.tv/kow/program/program_121.php
*/
import flash.display.Sprite;
import flash.events.Event;
import flash.events.KeyboardEvent;
import flash.geom.Matrix;
import flash.utils.ByteArray;
import flash.text.TextField;
import flash.text.TextFormat;
import flash.text.TextFieldAutoSize;
import flash.ui.Keyboard;
import frocessing.color.ColorHSV;
import mx.controls.Alert;
import flash.media.*;
import flash.net.*;
[SWF(width="465", height="465", frameRate="30", backgroundColor="0x222222")]
public class Main extends Sprite
{
private var block:Array;
private var field:Array;
private var px:int = 4;
private var py:int = 0;
private var frameCount:int = 0;
private var blockType:int;
private var nextBlock:int;
private var nextDrawBlock:Array;
private var lines:int = 0;
private var blocks:int = 0;
private var linesText:TextField;
private var blocksText:TextField;
private var gameoverText:TextField;
private var h:int = 11;
private var s:Number = 0.5;
private var v:Number = 0.3;
private var stop:Boolean = false;
private var gameover:Boolean = false;
private var seq:Array = new Array(3,4);
private var bgm:Boolean;
private var effects:Array;
private var snd:Sound;
private var channel:SoundChannel;
private var fieldStack:Array;
private var linesStack:Array;
private var blocksStack:Array;
public function Main()
{
Wonderfl.capture_delay(25);
nextBlock = seq[0];
createTextField(null, "Next:", 270, 35, 20);
createTextField(null, "Move", 270, 200, 20);
createTextField(null, "[A, S, D], [←, ↓, →]", 270, 220, 13);
createTextField(null, "Rotate", 270, 250, 20);
createTextField(null, "W, ↑, Enter, Space", 270, 270, 13);
createTextField(null, "黒いラインを越えたらGame Over", 270, 350, 13);
createTextField(null, "RでRestart,Pでモード切り替え", 270, 370, 13);
createTextField(null, "一回、画面をクリックしないと", 270, 400, 13);
createTextField(null, "キーが反応しないかもしれません", 270, 420, 13);
linesText = createTextField(null, "lines: 0", 270, 120, 20);
blocksText = createTextField(null, "blocks: 0", 270, 150, 20);
gameoverText = createTextField(null, "", 270, 300, 20, 0xFF0000);
block = new Array(21);
for (var i:int = 0; i < block.length; i++) block[i] = new Array(12);
initField();
fieldStack = new Array();
linesStack = new Array();
blocksStack = new Array();
bgm = true;
snd = new Sound();
//from http://upload.wikimedia.org/wikipedia/en/f/fe/Korobeiniki.mid
snd.load(new URLRequest("http://yambi.jp/resource/Korobeiniki.mp3"));
channel = snd.play(0, int.MAX_VALUE);
effects = new Array();
effects.push(new Sound());
//http://utm-game-web.hp.infoseek.co.jp/free-sound.htm
effects[0].load(new URLRequest("http://yambi.jp/resource/patu_mod.mp3"));
createBlock();
addEventListener(Event.ENTER_FRAME, onEnterFrame);
stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);
}
private function initField():void{
for (var y:int = 0; y < 21; y++){
for (var x:int = 0; x < 12; x++){
if (y == 20 || x == 0 || x == 11) block[y][x] = 9;
else block[y][x] = 0;
}
}
field = clone(block);
}
private function onEnterFrame(event:Event):void
{
if (frameCount++ % 15 == 0 && !stop && !gameover){
if (checkOverlap(py + 1, px)) lockBlock(), createBlock();
else moveBlock(py + 1, px);
}
draw();
}
private function draw():void
{
graphics.clear();
var hsv:ColorHSV = new ColorHSV();
var matrix:Matrix = new Matrix();
var color:int; // 変数定義、重複避け
matrix.createGradientBox(20, 20, 45 * Math.PI / 180);
for (var y:int = 0; y < 21; y++)
{
for (var x:int = 0; x < 12; x++)
{
matrix.createGradientBox(20, 20, 45 * Math.PI / 180, x * 20, y * 20);
if (block[y][x] == 0)
{
if(y>=h){
graphics.beginGradientFill("linear", [0xEEEEEE, 0xCCCCCC], [1.0, 1.0], [0, 255], matrix);
graphics.drawRect(x * 20, y * 20, 20, 20);
graphics.endFill();
}else{
graphics.beginGradientFill("linear", [0x999999, 0x777777], [1.0, 1.0], [0, 255], matrix);
graphics.drawRect(x * 20, y * 20, 20, 20);
graphics.endFill();
}
}
else if (block[y][x] == 9)
{
//graphics.beginGradientFill("linear", [0xFF556F, 0xFF979C], [1.0, 1.0], [0, 255], matrix);
graphics.beginGradientFill("linear", [0x777777, 0x333333], [1.0, 1.0], [0, 255], matrix);
graphics.drawRect(x * 20, y * 20, 20, 20);
graphics.endFill();
}
else
{
color = Block.color[block[y][x] - 1];
hsv.r = color >> 16 & 0xFF, hsv.g = color >> 8 & 0xFF, hsv.b = color & 0xFF;
hsv.s = s;
hsv.v = v;
graphics.beginGradientFill("linear", [hsv.value, Block.color[block[y][x] - 1]], [1.0, 1.0], [0, 255], matrix);
//graphics.beginFill(hsv.value);
graphics.drawRect(x * 20, y * 20, 20, 20);
graphics.endFill();
}
}
}
graphics.beginFill(0x000000);
graphics.drawRect(0,20*h,240,2);
graphics.endFill();
color = Block.color[nextBlock];
hsv.r = color >> 16 & 0xFF, hsv.g = color >> 8 & 0xFF, hsv.b = color & 0xFF;
hsv.s = s;
hsv.v = v;
for (y = 0; y < 4; y++)
{
for (x = 0; x < 4; x++)
{
if (nextDrawBlock[y][x])
{
matrix.createGradientBox(20, 20, 45 * Math.PI / 180, 350 + x * 20, 10 + y * 20);
graphics.beginGradientFill("linear", [hsv.value, Block.color[nextBlock]], [1.0, 1.0], [0, 255], matrix);
graphics.drawRect(350 + x * 20, 10 + y * 20, 20, 20);
graphics.endFill();
}
}
}
linesText.text = "lines: " + String(lines);
gameoverText.text = gameover?"Game Over!!":"";
}
private function createBlock():void
{
py = 0;
px = 4;
blockType = nextBlock;
nextBlock = seq[++blocks%seq.length];
nextDrawBlock = clone(Block.block[nextBlock]);
//nextBlock = Math.random() * Block.block.length;
blocksText.text = "blocks: " + blocks;
for (var y:int = 0; y < 4; y++)
{
for (var x:int = 0; x < 4; x++)
{
if (Block.block[blockType][y][x] && block[py + y][px + x]){
gameover = true;
}
block[py + y][px + x] += Block.block[blockType][y][x];
}
}
}
private function moveBlock(yy:int, xx:int):void
{
if(gameover) return;
for (var y:int = 0; y < 4; y++)
{
for (var x:int = 0; x < 4; x++)
{
block[py + y][px + x] -= Block.block[blockType][y][x];
}
}
py = yy;
px = xx;
for (y = 0; y < 4; y++)
{
for (x = 0; x < 4; x++)
{
block[py + y][px + x] += Block.block[blockType][y][x];
}
}
draw();
}
private function checkOverlap(yy:int, xx:int):Boolean{
for (var y:int = 0; y < 4; y++){
for (var x:int = 0; x < 4; x++) {
if (Block.block[blockType][y][x]){
if (field[yy + y][xx + x] != 0) return true;
}
}
}
return false;
}
private function lockBlock():void
{
fieldStack.push(clone(field));
linesStack.push(lines);
blocksStack.push(blocks);
for (var y:int = 0; y < 21; y++)
{
for (var x:int = 0; x < 12; x++)
{
field[y][x] = block[y][x];
}
}
checkLines();
for (y = 0; y < 21; y++)
{
for (x = 0; x < 12; x++)
{
block[y][x] = field[y][x];
if(y<h&&field[y][x]>0&&field[y][x]<9){
gameover = true;
}
}
}
}
private function controlBlock(yy:int, xx:int):void
{
if (!checkOverlap(py + yy, px + xx)) moveBlock(py + yy, px + xx)
else if (yy>0) lockBlock(), createBlock();
}
private function onKeyDown(event:KeyboardEvent):void
{
if (event.keyCode == 37) controlBlock(0, -1); // ←
if (event.keyCode == 40) controlBlock(1, 0); // ↓
if (event.keyCode == 39) controlBlock(0, 1); // →
if (event.keyCode == 38) turnBlock(); // ↑
if (event.keyCode == 65) controlBlock(0, -1); // A
if (event.keyCode == 68) controlBlock(0, 1); // D
if (event.keyCode == 83) controlBlock(1, 0); // S
if (event.keyCode == 87) turnBlock(); // W
if (event.keyCode == 82) restart();//R
if (event.keyCode == 80) pause();//P
if (event.keyCode == 77) toggleBGM();//M
if (event.keyCode == 85) undo();
if (event.keyCode == Keyboard.SPACE) turnBlock();
if (event.keyCode == Keyboard.ENTER) turnBlock();
}
private function undo():void{
if(fieldStack.length==0)return;
field = fieldStack.pop();
block = clone(field);
lines = linesStack.pop();
blocks = blocksStack.pop()-1;
gameover = false;
createBlock();
}
private function toggleBGM():void{
var cp:int = channel.position;
if(bgm)channel.stop();
else channel = snd.play(cp,int.MAX_VALUE);
bgm = !bgm;
}
private function playEffect(num:int):void{
effects[num].play();
}
private function restart():void{
gameover = false;
lines = 0;
blocks = 0;
nextBlock = seq[0];
initField();
fieldStack = new Array();
linesStack = new Array();
blocksStack = new Array();
createBlock();
}
private function pause():void{
stop = !stop;
}
private function turnBlock():void
{
if(gameover)return;
var temp:Array = clone(Block.block[blockType]);
for (var y:int = 0; y < 4; y++)
{
for (var x:int = 0; x < 4; x++)
{
Block.block[blockType][y][x] = temp[3 - x][y];
}
}
if (checkOverlap(py, px))
{
Block.block[blockType] = clone(temp);
return;
}
for (y = 0; y < 4; y++)
{
for (x = 0; x < 4; x++)
{
block[py + y][px + x] -= temp[y][x];
block[py + y][px + x] += Block.block[blockType][y][x];
}
}
draw();
}
private function checkLines():void
{
var found:Boolean;
for (var y:int = 19; y >= 0; y--)
{
found = true;
for (var x:int = 1; x <= 11; x++)
{
if (field[y][x] == 0)
{
found = false;
break;
}
}
if (found)
{
playEffect(0);
for (var xx:int = 1; xx <= 11; xx++) field[y][xx] == 0;
for (var yy:int = y; yy >= 1; yy--)
{
for (xx = 1; xx <= 11; xx++)
{
field[yy][xx] = field[yy - 1][xx];
}
}
y++;
lines++;
}
}
}
private function createTextField(parent:Sprite = null, text:String = "", x:int = 0, y:int = 0, fontSize:int = 13,c:uint=0xFFFFFF):TextField
{
var tf:TextField = new TextField();
tf.x = x, tf.y = y;
tf.defaultTextFormat = new TextFormat("_typeWriter", fontSize, c);
tf.text = text;
tf.selectable = false;
tf.autoSize = TextFieldAutoSize.LEFT;
if (parent) parent.addChild(tf);
else this.addChild(tf);
return tf;
}
private function clone(arg:*):*
{
var b:ByteArray = new ByteArray();
b.writeObject(arg);
b.position = 0;
return b.readObject();
}
}
}
class Block
{
public static var block:Array = [[[0, 0, 0, 0],
[0, 1, 1, 0],
[0, 1, 1, 0],
[0, 0, 0, 0]],
[[0, 0, 2, 0],
[0, 0, 2, 0],
[0, 0, 2, 0],
[0, 0, 2, 0]],
[[0, 0, 0, 0],
[0, 3, 3, 0],
[0, 3, 0, 0],
[0, 3, 0, 0]],
[[0, 0, 4, 0],
[0, 4, 4, 0],
[0, 4, 0, 0],
[0, 0, 0, 0]],
[[0, 5, 0, 0],
[0, 5, 5, 0],
[0, 0, 5, 0],
[0, 0, 0, 0]],
[[0, 0, 0, 0],
[0, 6, 0, 0],
[6, 6, 6, 0],
[0, 0, 0, 0]],
[[0, 0, 0, 0],
[0, 7, 7, 0],
[0, 0, 7, 0],
[0, 0, 7, 0]]];
//
public static var color:Array = [0xFFFF00, 0x00FFFF, 0x0000FF, 0xFF0000, 0x00FF00, 0xAA00FF, 0xFFA500];
public function Block(){}
}