TETRIS
→ RIGHT
← LEFT
↓ DROP
a ROTATE LEFT
s ROTATE RIGHT
/**
* Copyright WinField95 ( http://wonderfl.net/user/WinField95 )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/6K5w
*/
package
{
import flash.display.BitmapData;
import flash.display.Bitmap;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.KeyboardEvent;
import flash.geom.Point;
import flash.text.TextField;
import flash.text.TextFormat;
import flash.text.TextFieldAutoSize;
import flash.geom.Rectangle;
//import Test;
//import KeyController;
//import Piece;
/**
* ...
* @author Kyugo
*/
public class Main extends Sprite
{
const TITLE:int = 0;
const INIT:int = 1;
const PLAYING:int = 2;
const GAMEOVER:int = 3;
private var state:int;
private var title_tf1:TextField = new TextField();
private var title_tf2:TextField = new TextField();
private var gameover_tf1:TextField = new TextField();
private var gameover_tf2:TextField = new TextField();
private var field_bd:BitmapData = new BitmapData(500, 500, false, 0x000000);
private var field_bm:Bitmap = new Bitmap();
private var piece:Piece;
public function Main():void
{
addEventListener(Event.ENTER_FRAME, mainLoop);
state = TITLE;
this.graphics.beginFill(0x0);
this.graphics.drawRect(0, 0, 500, 500);
this.graphics.endFill();
KeyController.createInstance(this.stage);
}
private function mainLoop(event:Event):void {
switch (state)
{
case TITLE:
displayTitle();
break;
case INIT:
initGame();
break;
case PLAYING:
playGame();
break;
case GAMEOVER:
gameOver();
break;
}
}
private function displayTitle() {
trace("title");
title_tf1.scaleX = 40;
title_tf1.defaultTextFormat = new TextFormat("", 100, 0xFFFFFF, false);
title_tf1.text = "TETRIS";
stage.addChild(title_tf1);
title_tf2.scaleX = 40;
title_tf2.y = 400;
title_tf2.defaultTextFormat = new TextFormat("", 30, 0xFFFFFF, false);
title_tf2.text = "SPACE_KEY : GAMESTART";
title_tf2.x = -20;
stage.addChild(title_tf2);
if (KeyController.getInstance().getKey(32)) {
state = INIT;
stage.removeChild(title_tf1);
stage.removeChild(title_tf2);
}
}
private function initGame() {
trace("init");
field_bm.bitmapData = field_bd;
addChild(field_bm);
state = PLAYING;
piece = new Piece(this.stage);
}
private function draw():void{
field_bd.fillRect(new Rectangle(0, 0, 500, 500), 0x000000);
piece.draw(field_bd);
}
private function move():void{
piece.move();
}
private function playGame() {
trace("game");
//state = GAMEOVER;
if (!piece.active) {
if (piece.set(piece.next.shift())){
state = GAMEOVER;
return;
}
piece.next.push(Math.round(Math.random() * 6));
}
move()
draw();
}
private function gameOver() {
trace("gameover");
gameover_tf1.scaleX = 40;
gameover_tf1.defaultTextFormat = new TextFormat("", 60, 0xFFFFFF, false);
gameover_tf1.y = 50;
gameover_tf1.text = "GAMEOVER";
stage.addChild(gameover_tf1);
gameover_tf2.scaleX = 40;
gameover_tf2.y = 400;
gameover_tf2.defaultTextFormat = new TextFormat("", 30, 0xFFFFFF, false);
gameover_tf2.text = "SPACE_KEY : TITLE";
gameover_tf2.x = 20;
stage.addChild(gameover_tf2);
if (KeyController.getInstance().getKey(32)) {
state = TITLE;
stage.removeChild(piece.score_tf);
stage.removeChild(piece.message_tf);
stage.removeChild(piece.level_tf);
stage.removeChild(gameover_tf1);
stage.removeChild(gameover_tf2);
field_bd.fillRect(new Rectangle(0, 0, 500, 500), 0x000000);
}
}
}
}
import flash.display.Stage;
import flash.events.KeyboardEvent;
import flash.events.Event;
/**
* ...
* @author Kyugo
*/
// Singleton
class KeyController
{
private static var instance:KeyController;
//private static var keys:Array;
private static var push:int;
private static var timer:int;
const WAIT:int = 5;
public function KeyController(obj:Object) {
obj.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);
obj.addEventListener(KeyboardEvent.KEY_UP, onKeyUp);
obj.addEventListener(Event.ENTER_FRAME, countTimer);
//keys = new Array();
timer = 0;
}
public static function createInstance(obj:Object):void {
instance = new KeyController(obj);
}
public static function getInstance():KeyController {
return instance;
}
private function countTimer(event:Event):void
{
if (timer > 0) timer--;
trace(timer);
}
private function onKeyDown(event:KeyboardEvent):void {
//trace(event.keyCode);
//keys[event.keyCode] = true;
push = event.keyCode;
}
private function onKeyUp(event:KeyboardEvent):void {
//keys[event.keyCode] = false;
//push = event.keyCode;
push = -1;
}
public function getKey(k:int):Boolean{
if (timer > 0) {
return false;
}
if (push == k) {
timer = WAIT;
return true;
}
return false;
}
}
import flash.display.BitmapData;
import flash.display.Bitmap;
import flash.geom.Point;
import flash.text.TextField;
import flash.text.TextFormat;
import flash.text.TextFieldAutoSize;
import flash.filters.GlowFilter;
// import KeyController;
class Piece
{
public static const P_SIZE:int = 23;
public static const P_DIFF:int = 2;
public static const BLOCK_EDGE:BitmapData = new BitmapData(P_SIZE, P_SIZE, false, 0xAAAAAA);
// 色
public static const COLOR/*int*/:Array = [0x0,0xFFFF00, 0x00FFFF, 0x00FF00, 0xFF0000, 0x0000FF, 0xFF4500, 0x800080,0x444444];
// 形状
private var shape:Array =
[
[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0]
];
public static const SHAPE:Array =
[
[
[0, 0, 0, 0],
[0, 1, 1, 0],
[0, 1, 1, 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],
[0, 3, 3, 0],
[3, 3, 0, 0],
[0, 0, 0, 0]
],
[
[0, 0, 0, 0],
[4, 4, 0, 0],
[0, 4, 4, 0],
[0, 0, 0, 0]
],
[
[0, 0, 0, 0],
[5, 0, 0, 0],
[5, 5, 5, 0],
[0, 0, 0, 0]
],
[
[0, 0, 0, 0],
[0, 0, 6, 0],
[6, 6, 6, 0],
[0, 0, 0, 0]
],
[
[0, 0, 0, 0],
[0, 7, 0, 0],
[7, 7, 7, 0],
[0, 0, 0, 0]
]
];
public var id:int;
public var x:int;
public var y:int;
public var dy:Number;
public var next:Array = [];
//落下予測地点
public var ex:int;
public var ey:int;
public var field:Array = new Array();
public var active:Boolean;
const WIDTH:int = 12;
const HSTART = 5;
const HEIGHT:int = 20 + HSTART;
const DOWN:int = 40;
const RIGHT:int = 39;
const LEFT:int = 37;
const A:int = 65;
const S:int = 83;
public var time:int; // 猶予時間
const TIME:int = 10;
public var score:int; // スコア
public var addition:int // 増加スコア
public var score_tf:TextField = new TextField();
public var message_tf:TextField = new TextField(); // message
private var message_time:int;
const MESSAGE_TIME:int = 40;
public var level_tf:TextField = new TextField();
// スコアの詳細
const SINGLE:int = 100; //一列消し
const DOUBLE:int = 250; //二列消し
const TRIPLE:int = 500; //三列消し
const TETRIS:int = 1000; //四列消し
const DROP:int = 10; //落下させることによるスコア
private var G:Number; //落下スピード
const G1:Number = 0.05; //レベル1
const G2:Number = 0.08; //レベル2
const G3:Number = 0.12; //レベル3
const G4:Number = 0.15 //レベル4
const G5:Number = 0.30 //レベル5
//レベル変更基準点
const L1:int = 1000;
const L2:int = 2000;
const L3:int = 5000;
const L4:int = 10000;
const L5:int = 20000;
public function Piece(obj:Object)
{
// init field
for (var i:int = 0 ; i < HEIGHT ; i++) {
var array:Array = new Array();
for (var j:int = 0 ; j < WIDTH ; j++) {
if (i == 0 || j == 0 || j == WIDTH - 1) array.push(0);
else array.push(0);
}
field.push(array);
}
for (var i:int = 0 ; i < HEIGHT ; i++) {
for (var j:int = 0 ; j < WIDTH ; j++) {
if (i == HEIGHT-1 || j == 0 || j == WIDTH - 1) {
field[i][j] = 8;
//field_bd.copyPixels(BLOCK_EDGE, BLOCK_EDGE.rect, new Point(j * P_SIZE, i * P_SIZE));
//field_bd.copyPixels(BLOCK_GREY,BLOCK_GREY.rect,new Point(j*P_SIZE+P_DIFF/2,i*P_SIZE+P_DIFF/2));
}
else {
field[i][j] = 0;
}
}
}
for (var i:int = 0 ; i < 3 ; i++) {
next.push(Math.round(Math.random() * 6));
}
active = false;
time = TIME;
score = 0;
score_tf.scaleX = 200;
score_tf.defaultTextFormat = new TextFormat("", 20, 0xFFFFFF, false);
score_tf.y = 20;
obj.addChild(score_tf);
message_tf.scaleX = 200;
message_tf.defaultTextFormat = new TextFormat("", 20, 0xFFFF00, false);
message_tf.y = 40;
obj.addChild(message_tf);
level_tf.scaleX = 200;
level_tf.defaultTextFormat = new TextFormat("", 20, 0x00FF00, false);
level_tf.y = 60;
obj.addChild(level_tf);
level_tf.text = "Lv:1";
G = G1;
}
private function copyShape(shape1:Array,shape2:Array):void {
for (var i:int = 0 ; i < 4 ; i++) {
for (var j:int = 0 ; j < 4 ; j++) {
shape1[i][j] = shape2[i][j];
}
}
}
public function set(_id:int):Boolean{
id = _id;
ey = dy = y = 0;
ex = x = WIDTH / 2 - 1;
active = true;
copyShape(shape, SHAPE[id]);
return checkCollision(x, y, shape);
}
public function draw(field_bd:BitmapData):void {
var block:BitmapData = new BitmapData(P_SIZE-P_DIFF, P_SIZE-P_DIFF, false, 0x0);
for (var i:int = HSTART ; i < HEIGHT ; i++) {
for (var j:int = 0 ; j < WIDTH ; j++) {
if (field[i][j] != 0) {
block = new BitmapData(P_SIZE-P_DIFF, P_SIZE-P_DIFF, false, COLOR[field[i][j]]);
//field_bd.copyPixels(BLOCK_EDGE, BLOCK_EDGE.rect, new Point(j * P_SIZE, (i-HSTART) * P_SIZE));
field_bd.copyPixels(block,block.rect,new Point(j*P_SIZE+P_DIFF/2,(i-HSTART)*P_SIZE+P_DIFF/2));
//trace(Piece.P_SIZE);
}
}
}
for (var i:int = 0 ; i < 4 ; i++){
for (var j:int = 0 ; j < 4 ; j++){
if (shape[i][j] != 0) {
block = new BitmapData(P_SIZE-P_DIFF, P_SIZE-P_DIFF, false,COLOR[0]);
field_bd.copyPixels(BLOCK_EDGE, BLOCK_EDGE.rect, new Point((ex + j) * P_SIZE, (ey - HSTART + i) * P_SIZE));
field_bd.copyPixels(block,block.rect,new Point((ex + j)*P_SIZE+P_DIFF/2,(ey - HSTART + i)*P_SIZE+P_DIFF/2));
}
}
}
for (var i:int = 0 ; i < 4 ; i++){
for (var j:int = 0 ; j < 4 ; j++){
block = new BitmapData(P_SIZE-P_DIFF, P_SIZE-P_DIFF, false, COLOR[shape[i][j]]);
if(shape[i][j] != 0){
//field_bd.copyPixels(BLOCK_EDGE, BLOCK_EDGE.rect, new Point((x + j) * P_SIZE, (dy - HSTART + i) * P_SIZE));
field_bd.copyPixels(block,block.rect,new Point((x + j)*P_SIZE+P_DIFF/2,(dy - HSTART + i)*P_SIZE+P_DIFF/2));
}
}
}
// next;
for (var k:int = 0 ; k < next.length ; k++){
for (var i:int = 0 ; i < 4 ; i++){
for (var j:int = 0 ; j < 4 ; j++){
block = new BitmapData(P_SIZE-P_DIFF, P_SIZE-P_DIFF, false, COLOR[next[k]+1]);
if(SHAPE[next[k]][i][j] != 0){
//field_bd.copyPixels(BLOCK_EDGE, BLOCK_EDGE.rect, new Point((12 + j) * P_SIZE, (5 + i + k*5) * P_SIZE));
field_bd.copyPixels(block,block.rect,new Point((14 + j)*P_SIZE+P_DIFF/2,(5 + i + k*5)*P_SIZE+P_DIFF/2));
}
}
}
}
// スコアの更新と表示
score += addition;
score_tf.text = score.toString();
if (addition == 0 && message_time == 0) {
message_tf.text = "";
}
else if(addition != 0){
message_tf.text = "+ " + addition.toString();
message_time = MESSAGE_TIME;
}
else message_time--;
addition = 0;
if (score > L5) G = G5,level_tf.text = "Lv:5";
else if (score > L4) G = G4,level_tf.text = "Lv:4";
else if (score > L3) G = G3,level_tf.text = "Lv:3";
else if (score > L2) G = G2,level_tf.text = "Lv:2";
}
private function checkCollision(nx:int,ny:int,array:Array):Boolean{
for (var i:int = 0 ; i < 4 ; i++){
for (var j:int = 0 ; j < 4 ; j++){
if(array[i][j] != 0){
if (field[ny + i][nx + j] != 0) return true;
}
}
}
return false;
}
private function checkDrop(ndy:Number):Boolean{
var ny:int = ndy + 1.0;
return checkCollision(x,ny,shape);
}
private function rotateRight(array:Array):void {
for (var i:int = 0 ; i < 4 ; i++) {
for (var j:int = 0 ; j < 4 ; j++) {
array[j][4-1-i] = shape[i][j];
}
}
}
private function rotateLeft(array:Array):void {
for (var i:int = 0 ; i < 4 ; i++) {
for (var j:int = 0 ; j < 4 ; j++) {
array[4-1-j][i] = shape[i][j];
}
}
}
private function deleteBlock():void {
var cnt:int = 0;
for (var i:int = 0 ; i < HEIGHT-1 ; i++) {
var f:Boolean = true;
for (var j:int = 1 ; j < WIDTH-1 ; j++) {
if (field[i][j] == 0) f = false;
}
if (!f) continue;
cnt++;
for (var j:int = 1; j < WIDTH - 1 ; j++) field[i][j] = 0;
for (var ii:int = i - 1 ; ii >= 0 ; ii--) {
for (var j:int = 1 ; j < WIDTH - 1 ; j++){
var tmp:int = field[ii + 1][j];
field[ii + 1][j] = field[ii][j];
field[ii][j] = tmp;
}
}
}
if (cnt == 1) addition += SINGLE;
else if (cnt == 2) addition += DOUBLE;
else if (cnt == 3) addition += TRIPLE;
else if (cnt == 4) addition += TETRIS;
}
private function calcEstimateXY():void{
ex = x;
for ( ey = y ; ey < HEIGHT ; ey++) {
if (checkCollision(ex, ey+1, shape)) return;
}
}
public function move():void {
var nx:Number = x;
var ndy:Number = dy;
ndy += G;
if (checkDrop(ndy)) {
if(time == 0){
for (var i:int = 0 ; i < 4 ; i++){
for (var j:int = 0 ; j < 4 ; j++){
if(shape[i][j] != 0){
field[y + 1 + i][x + j] = shape[i][j];
}
}
}
deleteBlock();
active = false;
time = TIME;
return;
}
else time--;
}
else {
time = TIME;
dy = ndy;
if (dy - y >= 1.0) y = dy;
}
var array:Array =
[
[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0]
];
if (KeyController.getInstance().getKey(RIGHT)) { // move right
nx += 1;
if(!checkCollision(nx,y+1,shape))x = nx;
}
else if (KeyController.getInstance().getKey(LEFT)) { // move left
nx -= 1;
if(!checkCollision(nx,y+1,shape))x = nx;
}
else if (KeyController.getInstance().getKey(DOWN)) { // move left
addition += (ey - y) * DROP;
x = ex;
y = ey - 1;
dy = ey;
/*
for (var i:int = 0 ; i < 4 ; i++){
for (var j:int = 0 ; j < 4 ; j++){
if(shape[i][j] != 0){
field[y + 1 + i][x + j] = shape[i][j];
}
}
}
*/
//deleteBlock();
//active = false;
return;
}
else if (KeyController.getInstance().getKey(S)) { // rotate right
//copyShape(array, shape);
rotateRight(array);
if (!checkCollision(x, y+1, array)) copyShape(shape, array);
}
else if (KeyController.getInstance().getKey(A)) { // rotate left
rotateLeft(array);
if (!checkCollision(x, y+1, array)) copyShape(shape, array);
}
calcEstimateXY();
}
}