へたれゲーム
flash暦10日。
TamaGiri.as
/*============================================================ * File: TamaGiri.as * About: TamaGiri game controller */ class TamaGiri { private var root:MovieClip; private var canvas:MovieClip; private var CANVAS_DEPTH:Number = 100; private var TAMA_DEPTH:Number = 200; private var scoreField:TextField; private var SCORE_FIELD_DEPTH:Number = 101; private var lifeField:TextField; private var LIFE_FIELD_DEPTH:Number = 102; private var over:TextField; private var OVER_DEPTH:Number = 103; private var continue_button:MovieClip; private var CONTINUE_DEPTH:Number = 10400; private var titleField:TextField; private var TITLE_FIELD_DEPTH:Number = 105; private var start_button:MovieClip; private var START_DEPTH:Number = 10500; private var to_title_button:MovieClip; private var TO_TITLE_BUTTON_DEPTH:Number = 10600; private var bomField:TextField; private var BOM_FIELD_DEPTH:Number = 107; private var mySound:Sound; private var mySound2:Sound; private var tamaList:Array; private var GAME_OVER_TAMA_AWAY:Number = 10; private var BOM_ENEMY:Number = 10; private var is_mouse_pressed:Boolean; private var last_x:Number; private var last_y:Number; private var last_date_num:Number; private var tamaCutTotal:Number; private var tamaIndex:Number; private var tamaAwayTotal:Number; private var bom:Number; function TamaGiri(parent:MovieClip) { root = parent; init(); init_op(); } function init() { over = undefined; continue_button = undefined; titleField = undefined; start_button = undefined; root.createEmptyMovieClip("canvas", CANVAS_DEPTH); canvas = root["canvas"]; tamaList = new Array(); setupEventListener(); is_mouse_pressed = false; last_x = 0; last_y = 0; var last_date:Date = new Date(); last_date_num = last_date.valueOf(); tamaCutTotal = 0; tamaIndex = 0; tamaAwayTotal = 0; bom = 0; Tama.sum = 0; var format:TextFormat = new TextFormat(); format.size = 30; // bom canvas.createTextField("bom", BOM_FIELD_DEPTH, Stage.width-600, Stage.height-50, 100,40); bomField = canvas["bom"]; bomField.autoSize = true; bomField.setNewTextFormat(format); bomField.text = "bom: " + Math.floor(bom / BOM_ENEMY); // score canvas.createTextField("score", SCORE_FIELD_DEPTH, Stage.width-400, Stage.height-50, 200,40); scoreField = canvas["score"]; scoreField.autoSize = true; scoreField.setNewTextFormat(format); scoreField.text = "SCORE: " + tamaCutTotal; //life canvas.createTextField("life", LIFE_FIELD_DEPTH, Stage.width-150, Stage.height-50, 100,40); lifeField = canvas["life"]; lifeField.autoSize = true; lifeField.setNewTextFormat(format); lifeField.text = "LIFE: " + (GAME_OVER_TAMA_AWAY - tamaAwayTotal); } function init_op() { setupOpenningEventListener(); var format:TextFormat = new TextFormat(); format.size = 100; canvas.createTextField("title", TITLE_FIELD_DEPTH, Stage.width/2-100, Stage.height/2-100, 200,40); titleField = canvas["title"]; titleField.autoSize = "center"; titleField.setNewTextFormat(format); titleField.text = "Tama Giri !!"; var loader:MovieClipLoader = new MovieClipLoader(); var loader_event_object:Object = new Object; canvas.createEmptyMovieClip("start", START_DEPTH); start_button = canvas["start"]; loader_event_object.info = {x:Stage.width/2-100, y:Stage.height/2+100}; var self:TamaGiri = this; loader_event_object.onLoadComplete = function(mc:MovieClip) { mc._x = this.info.x; mc._y = this.info.y; mc.onRelease = function() { self.init(); }; }; loader.addListener(loader_event_object); loader.loadClip("img/start.jpg", start_button); } function setupOpenningEventListener() { var self:TamaGiri = this; root.onEnterFrame = function() { self.onOpenningEnterFrameHandler(); }; } function setupEventListener() { var self:TamaGiri = this; root.onEnterFrame = function() { self.onEnterFrameHandler(); }; root.onMouseDown = function() { self.onMouseDownHandler(); }; root.onMouseUp = function() { self.onMouseUpHandler(); }; root.onReleaseOutside = function() { self.onReleaseOutsideHandler(); }; root.onRollOut = function() { self.onRollOutHandler(); }; } function onOpenningEnterFrameHandler() :Void { if (tamaList.length < 20) { if (probability(5)) { canvas.createEmptyMovieClip("tama" + tamaIndex, TAMA_DEPTH+tamaIndex); tamaList.push(new Tama(canvas["tama" + tamaIndex])); tamaIndex++; } } // 玉の走査 var newTamaList:Array = new Array(); for(var i:Number = 0; i < tamaList.length; i++) { // 削除 if (! tamaList[i].isVisible()) { if (tamaList[i].status() == Tama.TAMA_DOWN) { tamaAwayTotal++; } tamaList[i].remove(); delete tamaList[i]; } else { // hit test if (is_mouse_pressed && tamaList[i].status() == Tama.TAMA_DOWN && tamaList[i].isHit(last_x,last_y, root._xmouse,root._ymouse)) { tamaCutTotal++; bom++; } // 次回も利用 newTamaList.push(tamaList[i]); } } tamaList = newTamaList; last_x=root._xmouse; last_y=root._ymouse; // スコア、ライフ表示 scoreField.text = "SCORE: " + tamaCutTotal; lifeField.text = "LIFE: " + (GAME_OVER_TAMA_AWAY - tamaAwayTotal); bomField.text = "bom: " + Math.floor(bom / BOM_ENEMY); } function onEnterFrameHandler() :Void { // 玉の生成 if (tamaList.length < (Math.floor(tamaCutTotal/5) + 1)) { if (probability(5)) { canvas.createEmptyMovieClip("tama" + tamaIndex, TAMA_DEPTH+tamaIndex); tamaList.push(new Tama(canvas["tama" + tamaIndex])); tamaIndex++; } } // 玉の走査 var newTamaList:Array = new Array(); for(var i:Number = 0; i < tamaList.length; i++) { // 削除 if (! tamaList[i].isVisible()) { if (tamaList[i].status() == Tama.TAMA_DOWN) { tamaAwayTotal++; } tamaList[i].remove(); delete tamaList[i]; } else { // hit test if (is_mouse_pressed && tamaList[i].status() == Tama.TAMA_DOWN && tamaList[i].isHit(last_x,last_y, root._xmouse,root._ymouse)) { tamaCutTotal++; bom++; if (tamaCutTotal % 20 == 0) { tamaAwayTotal--; } } // 次回も利用 newTamaList.push(tamaList[i]); } } tamaList = newTamaList; last_x=root._xmouse; last_y=root._ymouse; // スコア、ライフ表示 scoreField.text = "SCORE: " + tamaCutTotal; lifeField.text = "LIFE: " + (GAME_OVER_TAMA_AWAY - tamaAwayTotal); bomField.text = "bom: " + Math.floor(bom / BOM_ENEMY); // ゲームオーバー if (tamaAwayTotal >= GAME_OVER_TAMA_AWAY) { var self:TamaGiri = this; for(var i:Number = 0; i < tamaList.length; i++) { tamaList[i].gameOver(); } tamaList = undefined; root.onEnterFrame = function () { self.onGameOverFrame(); } // game over } } function onGameOverEnterFrameHandler() :Void { if (tamaList.length < 20) { if (probability(5)) { canvas.createEmptyMovieClip("tama" + tamaIndex, TAMA_DEPTH+tamaIndex); tamaList.push(new Tama(canvas["tama" + tamaIndex])); tamaIndex++; } } // 玉の走査 var newTamaList:Array = new Array(); for(var i:Number = 0; i < tamaList.length; i++) { // 削除 if (! tamaList[i].isVisible()) { tamaList[i].remove(); delete tamaList[i]; } else { // hit test if (is_mouse_pressed && tamaList[i].status() == Tama.TAMA_DOWN && tamaList[i].isHit(last_x,last_y, root._xmouse,root._ymouse)) { bom++; } // 次回も利用 newTamaList.push(tamaList[i]); } } tamaList = newTamaList; last_x=root._xmouse; last_y=root._ymouse; // スコア、ライフ表示 scoreField.text = "SCORE: " + tamaCutTotal; lifeField.text = "LIFE: " + (GAME_OVER_TAMA_AWAY - tamaAwayTotal); } function onGameOverFrame() :Void { canvas.createTextField("over", OVER_DEPTH, Stage.width/2-200, Stage.height/2-40, 200, 40); over = canvas["over"]; var format:TextFormat = new TextFormat(); format.size = 50; over.setNewTextFormat(format); over.text = "GAME OVER"; over.autoSize = "center"; var self:TamaGiri = this; // continue var loader:MovieClipLoader = new MovieClipLoader(); var loader_event_object:Object = new Object; canvas.createEmptyMovieClip("continue", CONTINUE_DEPTH); continue_button = canvas["continue"]; loader_event_object.info = {x:Stage.width/2+75, y:Stage.height/2-31}; loader_event_object.onLoadComplete = function(mc:MovieClip) { mc._x = this.info.x; mc._y = this.info.y; mc.onRelease = function() { self.init(); }; }; loader.addListener(loader_event_object); loader.loadClip("img/continue.jpg", continue_button); // to title var loader_a:MovieClipLoader = new MovieClipLoader(); var loader_event_object_a:Object = new Object; canvas.createEmptyMovieClip("to_title", TO_TITLE_BUTTON_DEPTH); to_title_button = canvas["to_title"]; loader_event_object_a.info = {x:Stage.width/2+75, y:Stage.height/2+20}; loader_event_object_a.onLoadComplete = function(mc:MovieClip) { mc._x = this.info.x; mc._y = this.info.y; mc.onRelease = function() { self.init(); self.init_op(); }; }; loader_a.addListener(loader_event_object_a); loader_a.loadClip("img/title.jpg", to_title_button); tamaList = new Array(); root.onEnterFrame = function () { self.onGameOverEnterFrameHandler(); }; } function onMouseDownHandler() :Void { last_x=root._xmouse; last_y=root._ymouse; var now:Date = new Date(); var now_num:Number = now.valueOf(); if (now_num - last_date_num < 1000) { if (bom - BOM_ENEMY >= 0) { bom -= BOM_ENEMY; for(var i:Number = 0; i < tamaList.length; i++) { tamaList[i].forceHit(); } now_num -= 2000; } } last_date_num = now_num; is_mouse_pressed = true; } function onMouseUpHandler() :Void { is_mouse_pressed = false; } function onReleaseOutsideHandler() :Void { is_mouse_pressed = false; } function onRollOutHandler() :Void { is_mouse_pressed = false; } // [p]%の確立でtrueを返す private function probability(p:Number) :Boolean { return Math.random() < (p / 100); } static function main() :Void { var base:TamaGiri = new TamaGiri(_root); } }
Tama.as
/*============================================================ * File: Tama.as * About: Tama class */ class Tama { static var TAMA_DOWN:Number = 0; static var TAMA_HIT:Number = 1; static var TAMA_HIT_FORCE:Number = 2; static var sum: Number = 0; private var mc :MovieClip; private var state :Number; private var TAMA_STATE_ALIVE :Number = 0; private var TAMA_STATE_TO_DIE :Number = 1; private var TAMA_STATE_DIE :Number = 2; private var TAMA_R :Number = 30; private var TAMA_MARGIN:Number = 40; private var COLOR_BLACK:Number = 0x000000; private var speed:Number = 1; private var g:Number = 9.8; private var div:Number = 24; private var cycle_flag:Number; private var last_x:Number; private var last_y:Number; static function col( t ) { var tx = Math.PI*2/3; while( Math.PI*2<t ){ t-=Math.PI*2; } if ( 0<=t && t<=tx ){ return 0; } return Math.floor( 128-Math.cos((t-tx)*1.5)*127 ); } static function getColor() :Number { var t:Number = sum; var rgb = col(t)*0x10000 + col(t+Math.PI*2/3)*0x100 + col(t+Math.PI*4/3); sum++; return rgb; } function Tama(_mc :MovieClip) { state = Tama.TAMA_DOWN; mc = _mc; mc._y = -TAMA_R; mc._x = downPoint(); last_y = mc._y; last_x = mc._x; // mc.lineStyle(0, COLOR_BLACK); // mc.beginFill(COLOR_BLACK); var color:Number = getColor(); mc.lineStyle(0, color); mc.beginFill(color); // form if (probability(30)) { drawCircle(mc, 0,0, TAMA_R); } else if (probability(60)) { drawSquare(mc, 0, 0, TAMA_R*2); } else { drawTriangle(mc,0,0, TAMA_R*1.5); } mc.endFill(); // rotation if (probability(50)) { cycle_flag = 1; } else { cycle_flag = -1; } var self:Tama = this; mc.onEnterFrame = function() { self.down(); }; } function remove() { mc.removeMovieClip(); } private function downPoint() :Number { return Math.random() * (Stage.width - 2*TAMA_MARGIN) + TAMA_MARGIN; } function down() { last_x = mc._x; last_y = mc._y; // 下まで行ききった if (mc._y > Stage.height + TAMA_R) { mc._visible = false; } mc._rotation = mc._rotation + cycle_flag * 5; speed = speed + g / div; mc._y = (mc._y + speed * 1); } function hidding() :Void { if (mc._alpha < 1) { mc._visible = false; } else { mc._alpha = mc._alpha * 0.75; } } function gameOver() :Void { mc.stop(); } function isVisible():Boolean { return mc._visible; } function status():Number { return state; } private function isHit(x1:Number, y1:Number, x2:Number, y2:Number):Boolean { if (mc.hitTest(x1,y2, true)) { state = Tama.TAMA_HIT; var self:Tama = this; mc.onEnterFrame = function() { self.hidding(); }; return true; } return false; } function forceHit() :Void { state = Tama.TAMA_HIT_FORCE; var self:Tama = this; mc.onEnterFrame = function() { self.hidding(); }; } // 円を描く function drawCircle(mc:MovieClip, x:Number, y:Number, r:Number):Void { mc.moveTo(x+r, y); mc.curveTo(r+x, Math.tan(Math.PI/8)*r+y, Math.sin(Math.PI/4)*r+x, Math.sin(Math.PI/4)*r+y); mc.curveTo(Math.tan(Math.PI/8)*r+x, r+y, x, r+y); mc.curveTo(-Math.tan(Math.PI/8)*r+x, r+y, -Math.sin(Math.PI/4)*r+x, Math.sin(Math.PI/4)*r+y); mc.curveTo(-r+x, Math.tan(Math.PI/8)*r+y, -r+x, y); mc.curveTo(-r+x, -Math.tan(Math.PI/8)*r+y, -Math.sin(Math.PI/4)*r+x, -Math.sin(Math.PI/4)*r+y); mc.curveTo(-Math.tan(Math.PI/8)*r+x, -r+y, x, -r+y); mc.curveTo(Math.tan(Math.PI/8)*r+x, -r+y, Math.sin(Math.PI/4)*r+x, -Math.sin(Math.PI/4)*r+y); mc.curveTo(r+x, -Math.tan(Math.PI/8)*r+y, r+x, y); } // FIXME: draw function drawTriangle(mc:MovieClip, x:Number, y:Number, l:Number) :Void { var n:Number = 2 * l / Math.sqrt(3); mc.moveTo(x, y - (n*2/3) ); mc.lineTo(x + l*Math.sqrt(2)/2, y + (n*1/3) ); mc.lineTo(x - l*Math.sqrt(2)/2, y + (n*1/3) ); mc.lineTo(x, y - (n*2/3) ); } function drawSquare(mc:MovieClip, x:Number, y:Number, l:Number) :Void { mc.moveTo(x-l/2, y-l/2); mc.lineTo(x-l/2, y+l/2); mc.lineTo(x+l/2, y+l/2); mc.lineTo(x+l/2, y-l/2); mc.lineTo(x-l/2, y-l/2); } // [p]%の確立でtrueを返す private function probability(p:Number) :Boolean { return Math.random() < (p / 100); } }
11/2-4は文化祭だったので、そのときwiiで動かして遊んだ。出し物の本命は山田ウイルスの感染実演だったので、これは脇役だったけど。
今一週間たって冷静にみると、ぼろぼろだな。以下反省点。
- 三角形の描写は適当。正三角形ではない(汗
- 色付けは参考にしたソースをコピペ、、
- コピペばかり。リファクタリングしていない。
- 状態遷移でコールバック関数を丸々入れ替えている。ソースを追わないと混乱する。