エクストリーム・ブロックくずし
本気でブロックくずしのプロを目指している方向けです。
/**
* Copyright o8que ( http://wonderfl.net/user/o8que )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/sUIo
*/
// forked from o8que's BlockKuzuser
package {
import flash.display.Sprite;
import flash.events.Event;
[SWF(width="465",height="465",frameRate="60",backgroundColor="0x000000")]
public class Main extends Sprite {
private var _state:MainState;
public function Main() {
graphics.beginFill(0x000000);
graphics.drawRect(0,0,465,465);
graphics.endFill();
var preloader:Preloader = new Preloader(this);
//["Aqua","Azuki","Cinecaption","Mona","Sazanami","YSHandy","VLGothic","IPAGP","IPAM","UmeUgo","UmePms","Bebas"]
preloader.addFontLoadingRequest(["Aqua","Mona","IPAGP"]);
preloader.addEventListener(Event.COMPLETE, initialize);
preloader.load();
}
private function initialize(event:Event):void {
event.target.removeEventListener(Event.COMPLETE, initialize);
//TextBuilder.deviceFonts = true;
addChild(_state = new MainState());
_state.changeState(new TitleScene(_state));
}
}
}
/* ------------------------------------------------------------------------------------------------
* State
* ------------------------------------------------------------------------------------------------
*/
//package {
import flash.display.Sprite;
import org.libspark.betweenas3.events.TweenEvent;
//public
class State extends Sprite {
private var _main:MainState;
private var _currentChild:State;
private var _previousChild:State;
private var _isPlaying:Boolean;
public function State(main:MainState) {
_main = main;
_currentChild = _previousChild = null;
_isPlaying = false;
}
public final function changeState(nextState:State):void {
if (_currentChild) {
_previousChild = _currentChild;
_currentChild.exit();
}
_currentChild = nextState;
_currentChild.enter();
}
public final function revertToPrevious():void {
if (!_previousChild) { return; }
_currentChild.exit();
_currentChild = _previousChild;
_currentChild.enter();
}
protected function enter():void { play(); }
protected function update():void { if (isPlaying) updateChild(); }
protected function exit():void { stop(); }
protected final function play(event:TweenEvent = null):void { _isPlaying = true; }
protected final function updateChild():void { _currentChild.update(); }
protected final function stop():void { _isPlaying = false; }
protected final function get main():MainState { return _main; }
protected final function get isPlaying():Boolean { return _isPlaying; }
}
//}
/* ------------------------------------------------------------------------------------------------
* MainState
* ------------------------------------------------------------------------------------------------
*/
//package {
import flash.events.Event;
//public
class MainState extends State {
public function MainState() {
super(this);
enter();
addEventListener(Event.ENTER_FRAME, function(event:Event):void { update(); } );
}
}
//}
/* ------------------------------------------------------------------------------------------------
* TitleScene
* ------------------------------------------------------------------------------------------------
*/
//package {
import flash.events.MouseEvent;
import flash.text.TextField;
import org.libspark.betweenas3.BetweenAS3;
import org.libspark.betweenas3.easing.*;
import org.libspark.betweenas3.tweens.ITween;
//public
class TitleScene extends State {
private var _clickToStartTween:ITween;
public function TitleScene(main:MainState) {
super(main);
graphics.beginFill(0x000000);
graphics.drawRect(0, 0, 465, 465);
graphics.endFill();
var bulider:TextBuilder =
(new TextBuilder()).align(TextBuilder.ALIGN_CENTER).autoSize(false, true)
.bold().font("Aqua", true, true).fontColor(0xFFFFFF).size(465, 232);
addChild(bulider.fontSize(50).build("ブロックくずし"));
var clickToStartLabel:TextField;
bulider.bold(false).position(0, 200, true);
addChild(clickToStartLabel = bulider.fontSize(30).build("click to start"));
_clickToStartTween = BetweenAS3.serial(
BetweenAS3.addChild(clickToStartLabel, this),
BetweenAS3.delay(BetweenAS3.removeFromParent(clickToStartLabel), 0.5, 0.5)
);
_clickToStartTween.stopOnComplete = false;
}
protected override function enter():void {
main.addChild(this);
_clickToStartTween.play();
addEventListener(MouseEvent.CLICK, startGame);
}
private function startGame(event:MouseEvent):void { main.changeState(new GameScene(main)); }
protected override function exit():void {
removeEventListener(MouseEvent.CLICK, startGame);
_clickToStartTween.stop();
main.removeChild(this);
}
}
//}
/* ------------------------------------------------------------------------------------------------
* GameScene
* ------------------------------------------------------------------------------------------------
*/
//package {
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.GradientType;
import flash.display.Sprite;
import flash.events.MouseEvent;
import flash.geom.ColorTransform;
import flash.geom.Matrix;
import flash.geom.Point;
import flash.geom.Rectangle;
import flash.text.TextField;
import org.libspark.betweenas3.BetweenAS3;
import org.libspark.betweenas3.easing.*;
//public
class GameScene extends State {
private var _level:int;
private var _lives:int;
private var _score:Number;
private var _scoreTemp:Number;
private var _combo:int;
private var _bounds:Rectangle;
private var _ball:Ball;
private var _blocks:Vector.<Block>;
private var _paddle:Paddle;
private var _screen:BitmapData;
private var _image:BitmapData;
private var _particles:Vector.<Particle>;
private var _levelDisplay:TextField;
private var _livesDisplay:TextField;
private var _scoreDisplay:TextField;
private var _isClear:Boolean;
public function GameScene(main:MainState) {
super(main);
_level = 0;
_lives = 0;
_score = _scoreTemp = 0;
_combo = 0;
_bounds = new Rectangle(0, 0, Const.STAGE_WIDTH, Const.STAGE_HEIGHT);
_ball = new Ball(Const.BALL_RADIUS);
//_blocks = new Vector.<Block>();
_paddle = new Paddle(Const.STAGE_WIDTH / 2, Const.STAGE_HEIGHT - Const.BLOCK_HEIGHT * 4, Const.PADDLE_WIDTH);
_isClear = false;
buildGUI();
}
/* UIの構築 */
private function buildGUI():void {
_screen = new BitmapData(465, 465, true, 0x00FFFFFF);
_image = Image.wall.clone();
_particles = new Vector.<Particle>();
addChild(new Bitmap(_screen));
var HUDHeight:int = 25;
var matrix:Matrix = new Matrix();
matrix.createGradientBox(465, HUDHeight, Math.PI / 2);
var HUD:Sprite = new Sprite();
HUD.graphics.beginGradientFill(GradientType.LINEAR, [0x404040, 0x404040], [0.8, 0.2], [0, 255], matrix);
HUD.graphics.drawRect(0, 0, 465, HUDHeight);
HUD.graphics.endFill();
addChild(HUD);
var labelBuilder:TextBuilder =
(new TextBuilder()).align(TextBuilder.ALIGN_CENTER).autoSize()
.font("IPAGP", true, true).fontColor(0xFFFFFF).fontSize(14)
.size(60, HUDHeight);
HUD.addChild(labelBuilder.position(52,0).build("Level"));
HUD.addChild(labelBuilder.position(100, 0, true).build("Lives"));
HUD.addChild(labelBuilder.position(100, 0, true).build("Score"));
var displayBuilder:TextBuilder =
(new TextBuilder()).align(TextBuilder.ALIGN_CENTER).autoSize(false, true).bold()
.font("Mona", true, true).fontColor(0xFFFFFF).fontSize(18).size(40, HUDHeight);
HUD.addChild(_levelDisplay = displayBuilder.position(112, 0).build("00"));
HUD.addChild(_livesDisplay = displayBuilder.position(100, 0, true).build(String(_lives)));
HUD.addChild(_scoreDisplay = displayBuilder.position(100, 0, true)
.autoSize().align(TextBuilder.ALIGN_RIGHT).size(100, HUDHeight).build("0"));
}
protected override function enter():void {
main.addChild(this);
changeState(new NormalView(main, this));
setupNewLevel();
}
/* 新しいレベルへの準備 */
private function setupNewLevel():void {
_level++;
_levelDisplay.text = String(_level);
// ブロックの初期化
_blocks = new Vector.<Block>();
for (var row:int = 1; row < 8; row++) {
for (var col:int = 0; col < Const.GRID_COLS - 1; col++) {
_blocks.push(new Block(Const.BLOCK_WIDTH * col + Const.BLOCK_WIDTH / 2, Const.BLOCK_HEIGHT * row, Const.BLOCK_WIDTH, Const.BLOCK_HEIGHT));
}
}
reset();
}
/* リセット(新しいレベル開始時・ボール落下時の) */
private function reset():void {
stop();
_combo = 0;
_ball.initialize(Const.STAGE_WIDTH / 2, Const.STAGE_HEIGHT / 2, Const.BALL_SPEED, 90);
play();
}
protected override function update():void {
// マウスの位置とパドルの位置を合わせる
_paddle.update(mouseX - (465 - Const.STAGE_WIDTH) / 2, _bounds);
if (isPlaying) { updateModel(); }
if(!_isClear){
draw();
updateChild();
//drawParticles();
}
}
private function updateModel():void {
// 壊れているブロックを削除し、一定数以下なら次のレベルへ
for (var i:int = _blocks.length - 1; i >= 0; i--) {
if (!_blocks[i].exists) { _blocks.splice(i, 1); }
}
if (_blocks.length < 1) { gotoNextLevel(); }
// ボールを移動して、落下していたら然るべき処理
var lastBallPosX:Number = _ball.x;
var lastBallPosY:Number = _ball.y;
if (!_ball.move(_bounds)) {
if (_lives == 0) {
endGame();
}else {
_lives--;
_livesDisplay.text = String(_lives);
reset();
}
}
// パドルとの当たり判定
if (_ball.y >= _paddle.topY && _paddle.topY > lastBallPosY) {
var collisionX:Number = lastBallPosX + (_ball.x - lastBallPosX) * (_paddle.topY - lastBallPosY) / (_ball.y - lastBallPosY);
if(_paddle.left <= collisionX && collisionX <= _paddle.right){
// パドルの中心からの距離を測り、近いなら貫通球に変化させる
var distFromCenterX:Number = collisionX - _paddle.centerX;
_ball.pierces = ((Math.abs(distFromCenterX) < 4) ? true : false);
// 当たり所によって跳ね返る角度を変化させる
_ball.angle = 270 + (75 * (distFromCenterX / _paddle.halfWidth));
// コンボ数リセット
_combo = 0;
}
}
// ブロックとの当たり判定
var bouncesH:Boolean = false;
var bouncesV:Boolean = false;
var hitsCorner:Boolean = false;
for (i = _blocks.length - 1; i >= 0; i--) {
var block:Block = _blocks[i];
if (_ball.left < block.right && _ball.right > block.left && _ball.top < block.bottom && _ball.bottom > block.top) {
// コンボ数を増やしスコアを加算する
_combo++;
var score:Number = 5 * Math.pow(2, _combo);
block.destroy(score);
_score += score;
// 貫通球でなければ跳ね返る
if (!_ball.pierces) {
if ((lastBallPosX < block.left || block.right < lastBallPosX) && (lastBallPosY < block.top || block.bottom < lastBallPosY)) {
hitsCorner = true;
}else{
if (lastBallPosX < block.left || block.right < lastBallPosX) { bouncesH = true; }
if (lastBallPosY < block.top || block.bottom < lastBallPosY) { bouncesV = true; }
}
}
}
}
if (hitsCorner && !bouncesH && !bouncesV) { bouncesH = bouncesV = true; }
_ball.bounce(bouncesH, bouncesV);
}
/* レベルクリア時の処理 */
private function gotoNextLevel():void {
setupNewLevel();
}
/* ゲームオーバー時の処理 */
private function endGame():void {
stop();
_isClear = true;
changeState(new GameClearScene(main, this));
}
/* 描画 */
private function draw():void {
// スコア表示のアニメーション
if (_score > _scoreTemp) {
_scoreTemp = Math.min(_scoreTemp + 11 + int((_score - _scoreTemp) / 8), _score);
_scoreDisplay.text = String(_scoreTemp);
}
_image.fillRect(_image.rect, 0x00FFFFFF);
// ブロックの描画
var blockImage:BitmapData = Image.block;
for (var i:int = 0; i < _blocks.length; i++) {
_image.copyPixels(blockImage, blockImage.rect, new Point(int(_blocks[i].left), int(_blocks[i].top)));
}
// ボールの描画
var ballPos:Matrix = new Matrix(1, 0, 0, 1, int(_ball.left), int(_ball.top));
var ballColorMultiplier:Number = (_ball.pierces) ? 0.3 : 1;
var ballColor:ColorTransform = new ColorTransform(1, ballColorMultiplier, ballColorMultiplier);
_image.draw(Image.ball, ballPos, ballColor);
// パドルの描画
_image.copyPixels(Image.paddle, Image.paddle.rect, new Point(int(_paddle.left), int(_paddle.topY)));
// 壁の描画
var wallImage:BitmapData = Image.wall;
_image.scroll(Const.WALL_THICKNESS, Const.WALL_THICKNESS);
_image.copyPixels(wallImage, wallImage.rect, new Point(0, 0), wallImage, new Point(0, 0), true);
}
/* パーティクルの描画 */
private function drawParticles():void {
var particleImage:BitmapData = Image.particle;
for (var i:int = _particles.length - 1; i >= 0; i--) {
var particle:Particle = _particles[i];
if (particle.update()) {
var matrix:Matrix = new Matrix();
matrix.translate( -1, -1);
matrix.scale(particle.scale, particle.scale);
matrix.rotate(particle.rotation);
matrix.translate(particle.x, particle.y);
_screen.draw(particleImage, matrix);
}else {
_particles.splice(i, 1);
}
}
}
protected override function exit():void {
main.removeChild(this);
}
public function addParticle(particle:Particle):void { _particles.push(particle); }
public function get score():Number { return _score; }
public function get ball():Ball { return _ball; }
public function get numBlocks():int { return _blocks.length; }
public function getBlockAt(index:int):Block { return _blocks[index]; }
public function get paddle():Paddle { return _paddle; }
public function get screen():BitmapData { return _screen; }
public function get image():BitmapData { return _image; }
}
//}
/* ------------------------------------------------------------------------------------------------
* Level01
* ------------------------------------------------------------------------------------------------
*/
//package {
import flash.display.BitmapData;
import flash.geom.Point;
//public
class Level01 extends State {
private var _game:GameScene;
private var _imageOffset:Point;
public function Level01(main:MainState, game:GameScene) {
super(main);
_game = game;
_imageOffset = new Point((465 - _game.image.width) / 2, 50);
}
protected override function update():void {
var screen:BitmapData = _game.screen;
var image:BitmapData = _game.image;
_imageOffset.x = 232 - Const.WALL_THICKNESS - int(_game.paddle.centerX);
screen.fillRect(screen.rect, 0x00FFFFFF);
screen.copyPixels(image, image.rect, _imageOffset);
// ブロックが壊されていたら、パーティクルの追加とスコア表示
for (var i:int = _game.numBlocks - 1; i >= 0; i--) {
var block:Block = _game.getBlockAt(i);
if (!block.exists) {
var correctX:int = block.centerX + _imageOffset.x + Const.WALL_THICKNESS;
var correctY:int = block.centerY + _imageOffset.y + Const.WALL_THICKNESS;
for (var j:int = 0; j < 10; j++) {
_game.addParticle(new Particle(correctX, correctY));
}
new ScoreIndicator(_game, correctX, correctY, String(block.score));
}
}
}
}
//}
/* ------------------------------------------------------------------------------------------------
* Level00
* ------------------------------------------------------------------------------------------------
*/
//package {
import flash.display.BitmapData;
import flash.geom.Point;
//public
class Level00 extends State {
private var _game:GameScene;
private var _imageOffset:Point;
public function Level00(main:MainState, game:GameScene) {
super(main);
_game = game;
_imageOffset = new Point((465 - _game.image.width) / 2, 50);
}
protected override function update():void {
var screen:BitmapData = _game.screen;
var image:BitmapData = _game.image;
_imageOffset.x = 232 - Const.WALL_THICKNESS - int(_game.ball.x);
_imageOffset.y = 232 - Const.WALL_THICKNESS - int(_game.ball.y);
screen.fillRect(screen.rect, 0x00FFFFFF);
screen.copyPixels(image, image.rect, _imageOffset);
// ブロックが壊されていたら、パーティクルの追加とスコア表示
// (正しい位置に補正するためにView側で処理する)
for (var i:int = _game.numBlocks - 1; i >= 0; i--) {
var block:Block = _game.getBlockAt(i);
if (!block.exists) {
var correctX:int = block.centerX + _imageOffset.x + Const.WALL_THICKNESS;
var correctY:int = block.centerY + _imageOffset.y + Const.WALL_THICKNESS;
for (var j:int = 0; j < 10; j++) {
_game.addParticle(new Particle(correctX, correctY));
}
new ScoreIndicator(_game, correctX, correctY, String(block.score));
}
}
}
}
//}
/* ------------------------------------------------------------------------------------------------
* Level99
* ------------------------------------------------------------------------------------------------
*/
//package {
import flash.display.BitmapData;
import flash.geom.Point;
//public
class Level99 extends State {
private var _game:GameScene;
private var _imageCenter:Point;
private var _imageOffset:Point;
public function Level99(main:MainState, game:GameScene) {
super(main);
_game = game;
_imageCenter = new Point((465 - _game.image.width) / 2, (465 - _game.image.height) / 2);
_imageOffset = new Point(_imageCenter.x, _imageCenter.y);
}
protected override function update():void {
var screen:BitmapData = _game.screen;
var image:BitmapData = _game.image;
_imageOffset.x = _imageCenter.x + ((_game.mouseX - 232.5) + (_game.ball.x - Const.STAGE_WIDTH / 2)) * 0.7;
_imageOffset.y = _imageCenter.y + ((_game.mouseY - 232.5) + (_game.ball.y - Const.STAGE_HEIGHT / 2)) * 0.7;
screen.fillRect(screen.rect, 0x00FFFFFF);
screen.copyPixels(image, image.rect, _imageOffset);
// ブロックが壊されていたら、パーティクルの追加とスコア表示
for (var i:int = _game.numBlocks - 1; i >= 0; i--) {
var block:Block = _game.getBlockAt(i);
if (!block.exists) {
var correctX:int = block.centerX + _imageOffset.x + Const.WALL_THICKNESS;
var correctY:int = block.centerY + _imageOffset.y + Const.WALL_THICKNESS;
for (var j:int = 0; j < 10; j++) {
_game.addParticle(new Particle(correctX, correctY));
}
new ScoreIndicator(_game, correctX, correctY, String(block.score));
}
}
}
}
//}
/* ------------------------------------------------------------------------------------------------
* NormalView
* ------------------------------------------------------------------------------------------------
*/
//package {
import flash.display.BitmapData;
import flash.geom.Point;
//public
class NormalView extends State {
private var _game:GameScene;
private var _imageOffset:Point;
public function NormalView(main:MainState, game:GameScene) {
super(main);
_game = game;
_imageOffset = new Point((465 - _game.image.width) / 2, 50);
}
protected override function update():void {
var screen:BitmapData = _game.screen;
var image:BitmapData = _game.image;
screen.fillRect(screen.rect, 0x00FFFFFF);
screen.copyPixels(image, image.rect, _imageOffset);
}
}
//}
/* ------------------------------------------------------------------------------------------------
* GameClearScene
* ------------------------------------------------------------------------------------------------
*/
//package {
import net.wonderfl.utils.WonderflAPI;
//public
class GameClearScene extends State {
private var _game:GameScene;
public function GameClearScene(main:MainState, game:GameScene) {
super(main);
_game = game;
}
protected override function enter():void {
graphics.beginFill(0x000000, 0.5);
graphics.drawRect(0, 0, 465, 465);
graphics.endFill();
_game.addChild(this);
ScoreWindowLoader.init(_game, new WonderflAPI(root.loaderInfo.parameters), onScoreWindowLoaded);
}
private function onScoreWindowLoaded():void {
var score:Number = _game.score;
if (score > int.MAX_VALUE) { score = int.MAX_VALUE; }
ScoreWindowLoader.show(score, onScoreWindowClosed);
}
private function onScoreWindowClosed():void {
main.changeState(new TitleScene(main));
}
protected override function exit():void {
_game.removeChild(this);
}
}
//}
/* ------------------------------------------------------------------------------------------------
* Ball
* ------------------------------------------------------------------------------------------------
*/
//package {
import flash.geom.Point;
import flash.geom.Rectangle;
//public
class Ball {
private var _position:Point;
private var _polar:Point;
private var _velocity:Point;
private var _radius:int;
public var pierces:Boolean;
public function Ball(radius:int) {
_position = new Point();
_polar = new Point();
_velocity = new Point();
_radius = radius;
pierces = false;
}
public function initialize(x:Number, y:Number, speed:Number, angle:Number):void {
_position.x = x;
_position.y = y;
_polar.x = speed;
_polar.y = angle;
pierces = false;
setVelocity();
}
private function setVelocity():void {
// 貫通球は速さアップ
var speed:Number = _polar.x * ((pierces) ? 1.5 : 1);
_velocity.x = speed * Math.cos(_polar.y * Math.PI / 180);
_velocity.y = speed * Math.sin(_polar.y * Math.PI / 180);
}
public function move(bounds:Rectangle):Boolean {
_position.x += _velocity.x;
_position.y += _velocity.y;
// 落下判定、上壁との当たり判定
var bouncesV:Boolean = false;
if (_position.y > bounds.bottom + _radius) {
return false;
}else if (_position.y < bounds.top + _radius) {
_position.y = bounds.top + _radius;
bouncesV = true;
}
// 左壁と右壁との当たり判定
var bouncesH:Boolean = false;
if (_position.x < bounds.left + _radius) {
_position.x = bounds.left + _radius;
bouncesH = true;
}else if (_position.x > bounds.right - _radius) {
_position.x = bounds.right - _radius;
bouncesH = true;
}
bounce(bouncesH, bouncesV);
return true;
}
public function bounce(horizontal:Boolean, vertical:Boolean):void {
if (horizontal) { _polar.y = (180 - _polar.y) + (Math.random() * 2 - 1); }
if (vertical) { _polar.y = -_polar.y + (Math.random() * 2 - 1); }
setVelocity();
}
public function get x():Number { return _position.x; }
public function get y():Number { return _position.y; }
public function get left():Number { return _position.x - _radius; }
public function get right():Number { return _position.x + _radius; }
public function get top():Number { return _position.y - _radius; }
public function get bottom():Number { return _position.y + _radius; }
public function get angle():Number { return _polar.y; }
public function set angle(value:Number):void {
_polar.y = value;
setVelocity();
}
}
//}
/* ------------------------------------------------------------------------------------------------
* Block
* ------------------------------------------------------------------------------------------------
*/
//package {
import flash.geom.Point;
//public
class Block {
private var _position:Point;
private var _width:int;
private var _height:int;
private var _exists:Boolean;
private var _score:Number;
public function Block(x:Number, y:Number, width:int, height:int) {
_position = new Point(x, y);
_width = width;
_height = height;
_exists = true;
_score = 0;
}
public function destroy(score:Number):void {
_exists = false;
_score = score;
}
public function get centerX():Number { return _position.x + _width / 2; }
public function get centerY():Number { return _position.y + _height / 2; }
public function get left():Number { return _position.x; }
public function get right():Number { return _position.x + _width; }
public function get top():Number { return _position.y; }
public function get bottom():Number { return _position.y + _height; }
public function get exists():Boolean { return _exists; }
public function get score():Number { return _score; }
}
//}
/* ------------------------------------------------------------------------------------------------
* Paddle
* ------------------------------------------------------------------------------------------------
*/
//package {
import flash.geom.Point;
import flash.geom.Rectangle;
//public
class Paddle {
private var _position:Point;
private var _halfWidth:int;
public function Paddle(centerX:Number, topY:Number, width:int) {
_position = new Point(centerX, topY);
_halfWidth = width / 2;
}
public function update(centerX:Number, bounds:Rectangle):void {
if (centerX < bounds.left + _halfWidth) {
centerX = bounds.left + _halfWidth;
}else if (centerX > bounds.right - _halfWidth) {
centerX = bounds.right - _halfWidth;
}
_position.x = centerX;
}
public function get centerX():Number { return _position.x; }
public function get topY():Number { return _position.y; }
public function get left():Number { return _position.x - _halfWidth; }
public function get right():Number { return _position.x + _halfWidth; }
public function get halfWidth():int { return _halfWidth; }
}
//}
/* ------------------------------------------------------------------------------------------------
* Particle
* ------------------------------------------------------------------------------------------------
*/
//package {
import flash.geom.Point;
//public
class Particle {
private var _position:Point;
private var _velocity:Point;
private var _scale:Number;
private var _rotation:Point;
public function Particle(x:Number, y:Number) {
_position = new Point(x, y);
_velocity = new Point(Math.random() * 8 - 4, Math.random() * 8 - 4);
_scale = Math.random() * 5 + 1;
_rotation = new Point(0, Math.random() * 6 - 3);
}
public function update():Boolean {
_velocity.y += 0.2;
_position.x += _velocity.x;
_position.y += _velocity.y;
_rotation.x += _rotation.y;
if (_position.y > 465) {
return false;
}else {
return true;
}
}
public function get x():Number { return _position.x; }
public function get y():Number { return _position.y; }
public function get scale():Number { return _scale; }
public function get rotation():Number { return _rotation.x; }
}
//}
/* ------------------------------------------------------------------------------------------------
* Image
* ------------------------------------------------------------------------------------------------
*/
//package {
import flash.display.BitmapData;
import flash.display.Sprite;
import flash.filters.BevelFilter;
import flash.filters.DropShadowFilter;
import flash.geom.Point;
import flash.geom.Rectangle;
//public
class Image {
private static var _wall:BitmapData;
private static var _block:BitmapData;
private static var _ball:BitmapData;
private static var _paddle:BitmapData;
private static var _particle:BitmapData;
private static function createWall():BitmapData {
var bmd:BitmapData = new BitmapData(Const.STAGE_WIDTH + Const.WALL_THICKNESS * 2, Const.STAGE_HEIGHT + Const.WALL_THICKNESS, true, 0xFFFFFFFF);
bmd.fillRect(new Rectangle(Const.WALL_THICKNESS, Const.WALL_THICKNESS, Const.STAGE_WIDTH, Const.STAGE_HEIGHT), 0x00FFFFFF);
bmd.applyFilter(bmd, bmd.rect, new Point(), new BevelFilter(2, 45, 0xC0C0C0, 1, 0x000000, 1, 1, 1));
return bmd;
}
private static function createBlock():BitmapData {
var bmd:BitmapData = new BitmapData(Const.BLOCK_WIDTH, Const.BLOCK_HEIGHT, true, 0xFFFFFFFF);
bmd.applyFilter(bmd, bmd.rect, new Point(), new BevelFilter(2, 45, 0xC0C0C0, 1, 0x000000, 1, 1, 1));
return bmd;
}
private static function createBall():BitmapData {
var size:int = Const.BALL_RADIUS + Const.BALL_RADIUS;
var bmd:BitmapData = new BitmapData(size, size, true, 0x00FFFFFF);
var sprite:Sprite = new Sprite();
sprite.graphics.beginFill(0xFFFFFF);
sprite.graphics.drawCircle(Const.BALL_RADIUS, Const.BALL_RADIUS, Const.BALL_RADIUS);
sprite.graphics.endFill();
sprite.filters = [new DropShadowFilter(1, 225, 0x000000, 1, Const.BALL_RADIUS, Const.BALL_RADIUS, 1, 1, true)];
bmd.draw(sprite);
return bmd;
}
private static function createPaddle():BitmapData {
var bmd:BitmapData = new BitmapData(Const.PADDLE_WIDTH, Const.BLOCK_HEIGHT / 2, true, 0xFFFFFFFF);
bmd.applyFilter(bmd, bmd.rect, new Point(), new BevelFilter(2, 45, 0xC0C0C0, 1, 0x000000, 1, 1, 1));
return bmd;
}
private static function createParticle():BitmapData {
var bmd:BitmapData = new BitmapData(2, 2, true, 0x80FFFFFF);
return bmd;
}
public static function get wall():BitmapData { return _wall ||= createWall(); }
public static function get block():BitmapData { return _block ||= createBlock(); }
public static function get ball():BitmapData { return _ball ||= createBall(); }
public static function get paddle():BitmapData { return _paddle ||= createPaddle(); }
public static function get particle():BitmapData { return _particle ||= createParticle(); }
}
//}
/* ------------------------------------------------------------------------------------------------
* Const
* ------------------------------------------------------------------------------------------------
*/
//package {
//public
class Const {
public static const BLOCK_WIDTH:int = 32;
public static const BLOCK_HEIGHT:int = 16;
public static const GRID_COLS:int = 8;
public static const GRID_ROWS:int = 24;
public static const BALL_SPEED:Number = 10;
public static const BALL_RADIUS:int = 5;
public static const PADDLE_WIDTH:int = 60;
public static const WALL_THICKNESS:int = 10;
public static const STAGE_WIDTH:int = BLOCK_WIDTH * GRID_COLS;
public static const STAGE_HEIGHT:int = BLOCK_HEIGHT * GRID_ROWS;
}
//}
/* ------------------------------------------------------------------------------------------------
* Preloader
* ------------------------------------------------------------------------------------------------
*/
//package {
import com.bit101.components.Label;
import com.bit101.components.ProgressBar;
import com.bit101.components.Style;
import flash.display.DisplayObjectContainer;
import flash.events.Event;
import flash.events.EventDispatcher;
import flash.utils.Dictionary;
import net.wonderfl.utils.FontLoader;
//public
class Preloader extends EventDispatcher {
private var _numAssets:int;
private var _numLoaded:int;
/* ローディング状況表示関連 */
private var _label:Label;
private var _progressBar:ProgressBar;
/* 画像読み込み関連 */
private var _loadsImages:Boolean;
private var _imageURLs:Object;
private var _imageLoaders:Dictionary;
private var _addToContainerFunc:Function;
/* フォント読み込み関連 */
private var _loadsFonts:Boolean;
private var _fontNames:Array;
private var _fontLoaders:Vector.<FontLoader>;
public function Preloader(parent:DisplayObjectContainer):void {
_numAssets = _numLoaded = 0;
Style.BACKGROUND = 0xFFFFFF;
Style.LABEL_TEXT = 0xFFFFFF;
Style.PROGRESS_BAR = 0x00FF00;
_label = new Label(parent, 182, 213, "Now Loading...");
_progressBar = new ProgressBar(parent, 182, 231);
_loadsImages = _loadsFonts = false;
}
/* 画像読み込み要求を行う */
public function addImageLoadingRequest(URLs:Object, addToContainerFunc:Function):void {
_loadsImages = true;
_imageURLs = URLs;
_imageLoaders = new Dictionary();
_addToContainerFunc = addToContainerFunc;
for (var name:String in _imageURLs) {
_numAssets++;
var loader:ExternalImageLoader = new ExternalImageLoader();
loader.addEventListener(Event.COMPLETE, assetLoaded);
_imageLoaders[name] = loader;
}
}
/* フォント読み込み要求を行う */
public function addFontLoadingRequest(names:Array):void {
_loadsFonts = true;
_fontNames = names;
_fontLoaders = new Vector.<FontLoader>();
for (var i:int = 0; i < _fontNames.length; i++) {
_numAssets++;
var loader:FontLoader = new FontLoader();
loader.addEventListener(Event.COMPLETE, assetLoaded);
_fontLoaders.push(loader);
}
}
public function load():void {
if (_numAssets == 0) { onEveryAssetLoaded(); return; }
_progressBar.maximum = _numAssets;
// 画像読み込みを開始する
if (_loadsImages) {
for (var name:String in _imageLoaders) {
_imageLoaders[name].load(_imageURLs[name]);
}
}
// フォント読み込みを開始する
if (_loadsFonts) {
for (var i:int = 0; i < _fontLoaders.length; i++) {
_fontLoaders[i].load(_fontNames[i]);
}
}
}
private function assetLoaded(event:Event):void {
event.target.removeEventListener(Event.COMPLETE, assetLoaded);
_numLoaded++;
_progressBar.value = _numLoaded;
if (_numLoaded == _numAssets) { onEveryAssetLoaded(); }
}
private function onEveryAssetLoaded():void {
if (_loadsImages) {
for (var name:String in _imageLoaders) {
_addToContainerFunc(name, _imageLoaders[name].content);
}
}
_label.parent.removeChild(_label);
_progressBar.parent.removeChild(_progressBar);
Style.BACKGROUND = 0xCCCCCC;
Style.LABEL_TEXT = 0x666666;
Style.PROGRESS_BAR = 0xFFFFFF;
dispatchEvent(new Event(Event.COMPLETE));
}
}
//}
/* ------------------------------------------------------------------------------------------------
* ExternalImageLoader
* ------------------------------------------------------------------------------------------------
*/
//package {
import flash.display.BitmapData;
import flash.display.Loader;
import flash.events.Event;
import flash.events.EventDispatcher;
import flash.net.URLRequest;
import flash.system.LoaderContext;
//public
class ExternalImageLoader extends EventDispatcher {
private var _content:BitmapData;
private var _temp1:Loader;
private var _temp2:Loader;
public function ExternalImageLoader() {
_content = null; _temp1 = new Loader(); _temp2 = new Loader();
}
public function load(url:String):void {
_temp1.contentLoaderInfo.addEventListener(Event.INIT, temp1Loaded);
_temp1.load(new URLRequest(url), new LoaderContext(true));
}
private function temp1Loaded(event:Event):void {
event.target.removeEventListener(Event.INIT, temp1Loaded);
_content = new BitmapData(int(_temp1.width), int(_temp1.height), true, 0x00ffffff);
_temp2.contentLoaderInfo.addEventListener(Event.INIT, temp2Loaded);
_temp2.loadBytes(_temp1.contentLoaderInfo.bytes);
}
private function temp2Loaded(event:Event):void {
event.target.removeEventListener(Event.INIT, temp2Loaded);
_content.draw(_temp2); _temp1.unload(); _temp2.unload();
dispatchEvent(new Event(Event.COMPLETE));
}
public function get content():BitmapData { return _content; }
}
//}
/* ------------------------------------------------------------------------------------------------
* TextBuilder
* ------------------------------------------------------------------------------------------------
*/
//package {
import flash.filters.GlowFilter;
import flash.text.AntiAliasType;
import flash.text.TextField;
import flash.text.TextFieldAutoSize;
import flash.text.TextFormat;
import flash.text.TextFormatAlign;
//public
class TextBuilder {
public static const ALIGN_LEFT:String = "left";
public static const ALIGN_RIGHT:String = "right";
public static const ALIGN_CENTER:String = "center";
public static var deviceFonts:Boolean = false;
private var _posX:Number;
private var _posY:Number;
private var _width:Number;
private var _height:Number;
private var _background:Boolean;
private var _backgroundColor:uint;
private var _border:Boolean;
private var _borderColor:uint;
private var _fontName:String;
private var _embedFonts:Boolean;
private var _advancedAntiAlias:Boolean;
private var _fontSize:int;
private var _fontColor:uint;
private var _bold:Boolean;
private var _textBorder:Boolean;
private var _textBorderColor:uint;
private var _textBorderBlur:Number;
private var _textBorderStrength:Number;
private var _align:String;
private var _autoSizeEnabled:Boolean;
private var _autoCorrectPositionY:Boolean;
private var _wordWrap:Boolean;
public function TextBuilder() {
clear();
}
public function clear():TextBuilder {
_posX = 0;
_posY = 0;
_width = 100;
_height = 100;
_background = false;
_backgroundColor = 0xffffff;
_border = false;
_borderColor = 0x000000;
_fontName = "Arial";
_embedFonts = false;
_advancedAntiAlias = false;
_fontSize = 12;
_fontColor = 0x000000;
_bold = false;
_textBorder = false;
_textBorderColor = 0xffff00;
_textBorderBlur = 4;
_textBorderStrength = 2;
_align = TextBuilder.ALIGN_LEFT;
_autoSizeEnabled = false;
_autoCorrectPositionY = false;
_wordWrap = false;
return this;
}
public function position(x:Number, y:Number, isRelative:Boolean = false):TextBuilder {
if (isRelative) {
_posX += x;
_posY += y;
}else{
_posX = x;
_posY = y;
}
return this;
}
public function size(width:Number, height:Number):TextBuilder {
_width = width;
_height = height;
return this;
}
public function background(enabled:Boolean, color:uint = 0xffffff):TextBuilder {
_background = enabled;
_backgroundColor = color;
return this;
}
public function border(enabled:Boolean, color:uint = 0x000000):TextBuilder {
_border = enabled;
_borderColor = color;
return this;
}
public function font(name:String, embed:Boolean = false, advancedAntiAlias:Boolean = false):TextBuilder {
if (deviceFonts) { return this; }
_fontName = name;
_embedFonts = embed;
_advancedAntiAlias = advancedAntiAlias;
return this;
}
public function fontSize(size:int):TextBuilder {
_fontSize = size;
return this;
}
public function fontColor(color:uint):TextBuilder {
_fontColor = color;
return this;
}
public function bold(enabled:Boolean = true):TextBuilder {
_bold = enabled;
return this;
}
public function textBorder(enabled:Boolean, color:uint = 0xffff00, blur:Number = 4, strength:Number = 2):TextBuilder {
_textBorder = enabled;
_textBorderColor = color;
_textBorderBlur = blur;
_textBorderStrength = strength;
return this;
}
public function align(value:String = TextBuilder.ALIGN_LEFT):TextBuilder {
_align = value;
return this;
}
public function autoSize(enabled:Boolean = true, correctsY:Boolean = true):TextBuilder {
_autoSizeEnabled = enabled;
_autoCorrectPositionY = correctsY;
return this;
}
public function wordWrap(enabled:Boolean = true):TextBuilder {
_wordWrap = enabled;
return this;
}
public function build(text:String):TextField {
var textField:TextField = new TextField();
textField.x = _posX;
textField.y = _posY;
textField.width = _width;
textField.height = _height;
var format:TextFormat = new TextFormat(_fontName, _fontSize, _fontColor, _bold);
if (_autoSizeEnabled) {
switch(_align) {
case TextBuilder.ALIGN_LEFT: { textField.autoSize = TextFieldAutoSize.LEFT; break; }
case TextBuilder.ALIGN_RIGHT: { textField.autoSize = TextFieldAutoSize.RIGHT; break; }
case TextBuilder.ALIGN_CENTER: { textField.autoSize = TextFieldAutoSize.CENTER; break; }
}
}else {
switch(_align) {
case TextBuilder.ALIGN_LEFT: { format.align = TextFormatAlign.LEFT; break; }
case TextBuilder.ALIGN_RIGHT: { format.align = TextFormatAlign.RIGHT; break; }
case TextBuilder.ALIGN_CENTER: { format.align = TextFormatAlign.CENTER; break; }
}
}
textField.embedFonts = _embedFonts;
textField.antiAliasType = (_advancedAntiAlias ? AntiAliasType.ADVANCED : AntiAliasType.NORMAL);
textField.defaultTextFormat = format;
textField.text = text;
if (textField.background = _background) { textField.backgroundColor = _backgroundColor; }
if (textField.border = _border) { textField.borderColor = _borderColor; }
if (_textBorder) { textField.filters = [new GlowFilter(_textBorderColor, 1, _textBorderBlur, _textBorderBlur, _textBorderStrength)]; }
if (!(textField.wordWrap = _wordWrap) && _autoCorrectPositionY) { textField.y += Math.max(0, Math.ceil((_height - (textField.textHeight + 4)) / 2)); }
textField.mouseEnabled = textField.selectable = false;
return textField;
}
public function clone():TextBuilder {
var clone:TextBuilder = new TextBuilder();
clone._posX = _posX;
clone._posY = _posY;
clone._width = _width;
clone._height = _height;
clone._background = _background;
clone._backgroundColor = _backgroundColor;
clone._border = _border;
clone._borderColor = _borderColor;
clone._fontName = _fontName;
clone._embedFonts = _embedFonts;
clone._advancedAntiAlias = _advancedAntiAlias;
clone._fontSize = _fontSize;
clone._fontColor = _fontColor;
clone._bold = _bold;
clone._textBorder = _textBorder;
clone._textBorderColor = _textBorderColor;
clone._textBorderBlur = _textBorderBlur;
clone._textBorderStrength = _textBorderStrength;
clone._align = _align;
clone._autoSizeEnabled = _autoSizeEnabled;
clone._autoCorrectPositionY = _autoCorrectPositionY;
clone._wordWrap = _wordWrap;
return clone;
}
}
//}
/* ------------------------------------------------------------------------------------------------
* ScoreIndicator
* ------------------------------------------------------------------------------------------------
*/
//package {
import flash.display.DisplayObjectContainer;
import flash.display.Sprite;
import flash.events.Event;
import flash.text.TextField;
import org.libspark.betweenas3.BetweenAS3;
import org.libspark.betweenas3.easing.*;
import org.libspark.betweenas3.tweens.ITween;
//public
class ScoreIndicator extends Sprite {
private var _chars:Vector.<TextField>;
private var _charIndex:int;
private var _numCompleted:int;
public function ScoreIndicator(parent:DisplayObjectContainer, centerX:int, bottomY:int, text:String) {
parent.addChild(this);
x = centerX;
y = bottomY;
mouseChildren = mouseEnabled = false;
_chars = new Vector.<TextField>();
_charIndex = 0;
_numCompleted = 0;
splitText(text);
alignChars();
playTween();
addEventListener(Event.ENTER_FRAME, checkEveryTweenCompleted);
}
private function splitText(text:String):void {
// 文字のスタイルを設定する
var builder:TextBuilder = new TextBuilder();
builder.autoSize(true, false).bold();
builder.font("Mona", true, true).fontColor(0xffffff).fontSize(14);
builder.textBorder(true, 0x404040, 2, 4);
for (var i:int = 0; i < text.length; i++) {
_chars.push(builder.build(text.charAt(i)));
}
}
private function alignChars():void {
var i:int, charsWidth:Number = 0;
for (i = 0; i < _chars.length; i++) {
charsWidth += _chars[i].textWidth;
}
if(_chars[0]){
_chars[0].x = -int(charsWidth / 2) - 2;
_chars[0].y = -_chars[0].textHeight - 2;
}
for (i = 1; i < _chars.length; i++) {
_chars[i].x = _chars[i - 1].x + _chars[i - 1].textWidth;
_chars[i].y = -_chars[i].textHeight - 2;
}
}
private function playTween(event:Event = null):void {
if (event) { removeEventListener(Event.ENTER_FRAME, playTween); }
var char:TextField = _chars[_charIndex++];
addChild(char);
// 各文字に適用するトゥーイン
var tween:ITween = BetweenAS3.bezierTo(char, { y: char.y }, { $y: -(char.textHeight * 2) }, 0.3, Sine.easeInOut);
tween.onComplete = tweenCompleteHandler;
tween.play();
if (_charIndex < _chars.length) {
addEventListener(Event.ENTER_FRAME, playTween);
}
}
private function tweenCompleteHandler():void {
_numCompleted++;
}
private function checkEveryTweenCompleted(event:Event):void {
if (_numCompleted == _chars.length) {
removeEventListener(Event.ENTER_FRAME, checkEveryTweenCompleted);
BetweenAS3.serial(
BetweenAS3.to(this, { alpha: 0 }, 0.3, Expo.easeIn),
BetweenAS3.removeFromParent(this)
).play();
}
}
}
//}
/* ------------------------------------------------------------------------------------------------
* ScoreWindowLoader
*
* bkzenさんのコードをそのまま拝借
* @see http://wonderfl.net/c/cuY4
* @see http://wonderfl.net/c/kYyY
* ------------------------------------------------------------------------------------------------
*/
//package {
import flash.display.DisplayObject;
import flash.display.DisplayObjectContainer;
import flash.display.Loader;
import flash.events.Event;
import flash.net.URLRequest;
import flash.system.LoaderContext;
import net.wonderfl.utils.WonderflAPI;
//public
class ScoreWindowLoader
{
private static var _top: DisplayObjectContainer;
private static var _api: WonderflAPI;
private static var _content: Object;
//private static const URL: String = "wonderflScore.swf";
private static const URL: String = "http://swf.wonderfl.net/swf/usercode/5/57/579a/579a46e1306b5770d429a3738349291f05fec4f3.swf";
private static const TWEET: String = "Playing ブロックくずし [score: %SCORE%] #wonderfl";
public static function init(top: DisplayObjectContainer, api: WonderflAPI, handler: Function): void
{
_top = top, _api = api;
var loader: Loader = new Loader();
var comp: Function = function(e: Event): void
{
loader.contentLoaderInfo.removeEventListener(Event.COMPLETE, comp);
_content = loader.content;
handler();
}
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, comp);
loader.load(new URLRequest(URL), new LoaderContext(true));
}
/**
* Wonderfl の Score API 用
* ランキング表示から Tweet までをひとまとめにしたSWF素材を使う
* @param score : 取得スコア
* @param closeHandler : Window が閉じるイベントハンドら
*/
public static function show( score: int, closeHandler: Function): void
{
var window: DisplayObject = _content.makeScoreWindow(_api, score, "ブロックくずし", 1, TWEET);
var close: Function = function(e: Event): void
{
window.removeEventListener(Event.CLOSE, close);
closeHandler();
}
window.addEventListener(Event.CLOSE, close);
_top.addChild(window);
}
}
//}