WIPアクションゲーム
上下左右で動いて、Zでジャンプします。
デバッグ用機能としてCを押している間重力がなくなり、上下左右で動けます。
マウスホイールでチップを選んでクリックで設置できます。ちくわととげは未実装です。
さしあたっての問題はほぼ解決した。あとは好みのブロックを追加していくのみ
/**
* Copyright marshkip ( http://wonderfl.net/user/marshkip )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/vA2g
*/
/*
ブロックの種類の追加を一般化しようと思ったが断念。
ブロックの種類をクラスにしてある時点でかなり厳しい気がする…
一応新しいブロックの追加方法。
1.差し替える画像を用意してGraphStrageクラスのURLを書き換える。
2.既存のブロックを継承したクラスを追加する。
3.f_(方向)の関数を適当にオーバーライドする。
4.MapクラスのaddBlock関数のswitchに追加したブロックについて書く。
5.必要であればMapChipクラスのブロック番号と画像番号の関連付けを変更する。
*/
package{
import flash.system.LoaderContext;
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.events.Event;
import flash.display.Loader;
import flash.display.LoaderInfo;
import flash.net.URLRequest;
import flash.display.Sprite;
import flash.text.TextField;
import flash.events.KeyboardEvent;
[SWF(width = "465", height = "465", frameRate = "60", backgroundColor="0xCCCCCC")]
public class Main extends Sprite{
public function Main() {
var gs:GraphStrage = new GraphStrage(this);
var tf:TextField = new TextField();
//var i :int = stage.height;
//tf.text = i.toString();
//addChild(tf);
//キーボードを使う準備
Key.Init();
stage.addEventListener(KeyboardEvent.KEY_DOWN,Key.keydown);
stage.addEventListener(KeyboardEvent.KEY_UP,Key.keyup);
}
public function makeMap():void{
//Grahicstrageから画像の準備が終わったら呼ばれる。
var map:Map = new Map();
this.addChild(map);
}
}
}
import flash.net.SharedObjectFlushStatus;
import flash.events.MouseEvent;
import flash.display.MovieClip;
import flash.geom.Matrix;
import flash.display.AVM1Movie;
import flash.text.TextFormat;
import flash.geom.Point;
import flash.geom.Rectangle;
import flash.system.LoaderContext;
import flash.text.TextField;
import flash.events.KeyboardEvent;
import flash.events.Event;
import flash.display.Shape;
import flash.display.Sprite;
import flash.display.Loader;
import flash.display.LoaderInfo;
import flash.net.URLRequest;
import flash.events.Event;
import flash.display.Bitmap;
import flash.display.BitmapData;
//トレース関数
class Trace{
private static var rownum:int;
private static var mc_parent:Sprite;
public function Trace(pas:Sprite){
mc_parent = pas;
}
public function outTrace(str:String):void{
var tf:TextField = new TextField();
tf.text = str;
mc_parent.addChild(tf);
}
}
//マップに並べるマップチップのクラス
class MapChip extends Sprite{
public var bmp:Bitmap; //ビットマップ
public var bmd:BitmapData;//ビットマップデータ
public static const chip_height:int = 24; //マップチップの高さ
public static const chip_width:int = 24; //マップチップの幅
public function MapChip(num:int){ //コンストラクタ
//ブロック番号と画像番号の関連付け
/*
どの画像番号(data配列のインデックス)がどのブロックと対応するかを決める
今はnum+16なので、0番ブロックが画像16、1番ブロックが画像17 … になってる
*/
bmd = GraphStrage.data[num + 16];
bmp = new Bitmap(bmd);
addChild(bmp);
//デバッグ用ブロック番号表示
//var tf:TextField = new TextField();
//tf.text = num.toString();
//addChild(tf);
}
public function changeChip(num:int):void{ //マップチップの内容を書き換える
bmp.bitmapData = GraphStrage.data[num+16];
}
}
//キャラの状態を表すクラス
class CharaState{
public var x:Number;
public var y:Number;
public var vx:Number;
public var vy:Number;
public var po_y:Number;
public var po_x:Number;
public var height:Number;
public var width:Number;
public var granding:Boolean;
public var walking:Boolean;
public function CharaState(cs:CharaState = null){
if(cs == null)
{
x = 0;
y = 0;
po_x = 0;
po_y = 0;
vx = 0;
vy = 0;
granding = false;
walking = false;
}
else{
getOtherState(cs);
}
}
public function getOtherState(cs:CharaState):void{
x = cs.x;
y = cs.y;
vx = cs.vx;
vy = cs.vy;
po_y = cs.po_y;
po_x = cs.po_x;
height = cs.height;
width = cs.width;
granding = cs.granding;
walking = cs.walking;
}
}
//ブロックの定義
//各種ブロックのスーパークラス 何もないところ
class Block extends MapChip{
public var blockable:Boolean;
public function Block(chip:int = 0){
super(chip);
blockable = false;
}
public function f_top(cs:CharaState):CharaState{
return cs;
}
public function f_left(cs:CharaState):CharaState{
return cs;
}
public function f_right(cs:CharaState):CharaState{
return cs;
}
public function f_bottom(cs:CharaState):CharaState{
return cs;
}
}
//ふつうのブロック
class Block_Normal extends Block{
public function Block_Normal(chip:int = 1){
super(chip);
blockable = true;
}
public override function f_top( cs:CharaState):CharaState{
var acs:CharaState = new CharaState(cs);
if(acs.vy > 0)acs.vy = 0;
acs.y = this.y - acs.height ;
//擬似的な摩擦による減速
if(acs.walking == false){
if(acs.vx >= 1)
acs.vx = acs.vx - 0.3;
else if(acs.vx <= -1)
acs.vx = acs.vx + 0.3;
else
acs.vx = 0;
}
else{
}
acs.granding = true;
return acs;
}
public override function f_left(cs:CharaState):CharaState{
var acs:CharaState = new CharaState(cs);
acs.x = (this.x - acs.width );
if(acs.vx > 0) acs.vx = 0;
return acs;
}
public override function f_right(cs:CharaState):CharaState{
var acs:CharaState = new CharaState(cs);
acs.x = (this.x + 24 );
if(acs.vx < 0) acs.vx = 0;
return acs;
}
public override function f_bottom(cs:CharaState):CharaState{
var acs:CharaState = new CharaState(cs);
acs.y = (this.y + 24);
if(acs.vy < 0)acs.vy = 0;
return acs;
}
}
//滑る氷のブロック
class Block_Ice extends Block_Normal{
public function Block_Ice(){
super(2);
blockable = true;
}
public override function f_top(cs:CharaState):CharaState{
var acs:CharaState = new CharaState(cs);
if(acs.vy > 0) acs.vy = 0;
acs.y = this.y - acs.height ;
//擬似的な摩擦による減速
if(acs.vx > 0)
acs.vx = acs.vx - 0.001;
else if(acs.vx < 0)
acs.vx = acs.vx + 0.001;
acs.granding = true;
return acs;
}
}
//跳ね返す音符ブロック
class Block_Note extends Block_Normal{
public function Block_Note(chip:int = 3){
super(chip);
blockable = true;
}
public override function f_top( cs:CharaState):CharaState{
var acs:CharaState = super.f_top(cs);
acs.vy = -10;
acs.granding = false;
return acs;
}
public override function f_left(cs:CharaState):CharaState{
var acs:CharaState = super.f_left(cs);
acs.vx = -5;
acs.granding = false;
return acs;
}
public override function f_right(cs:CharaState):CharaState{
var acs:CharaState = super.f_right(cs);
acs.vx = 5;
acs.granding = false;
return acs;
}
public override function f_bottom(cs:CharaState):CharaState{
var acs:CharaState = super.f_bottom(cs);
acs.vy = 5;
acs.granding = false;
return acs;
}
}
//下からすり抜け床
class Block_Rope extends Block_Normal{
public function Block_Rope(chip:int = 6){
super(chip);
blockable = false;
}
public override function f_top( cs:CharaState):CharaState{
var acs:CharaState = new CharaState(cs);
if((acs.vy >= 0) && ((acs.y + acs.height) - acs.vy <= this.y)){
acs = super.f_top(acs);
//acs.y -= 1;
}
return acs;
}
public override function f_left(cs:CharaState):CharaState{
return cs;
}
public override function f_right(cs:CharaState):CharaState{
return cs;
}
public override function f_bottom(cs:CharaState):CharaState{
return cs;
}
}
//乗ると消えるちくわブロック
class Block_Tikuwa extends Block_Normal{
private var timer:int;
public function Block_Tikuwa(chip:int = 4){
super(chip);
blockable = true;
}
public override function f_top( cs:CharaState):CharaState{
if(blockable)
{
super.f_top(cs);
timer = 10;
blockable = false;
this.addEventListener(Event.ENTER_FRAME , oEF);
}
return cs;
}
public function oEF(e:Event):void{
}
}
//画像を持ってきてとっておくクラス
class GraphStrage{
static public var data : Array;
static public var mapchip : Array;
static public var enpty : BitmapData;
public var mainptr:Main;
public var loader : Loader;
public function GraphStrage(ptr:Main) : void{
//mainへのアドレス
mainptr = ptr;
//dataには仮の画像を詰めておく
data = new Array();
data[0] = new BitmapData(24 , 24 , true , 0xFF6666FF );
enpty = new BitmapData(24 , 24 , true , 0xFF000000 );
//画像をもってくる
var url:String = "http://assets.wonderfl.net/images/related_images/8/89/8998/8998c1ebb15a1ee9e69df0cb7ca0d3df8f71e1d1";
/*
一番左上が0番、24×24の画像8個1行としてdata配列に読み込みます。
今は16番目から順番にブロック用画像として用いる設定。
もっとたくさん画像を使う場合はloadComp関数のforのループ回数を多くする。
*/
var urlr:URLRequest = new URLRequest(url);
loader = new Loader();
var linfo : LoaderInfo = loader.contentLoaderInfo;
linfo.addEventListener(Event.COMPLETE , loadComp );
loader.load(urlr,new LoaderContext(true));
}
public function loadComp(event:Event):void{
//ロードが完了したとき
var bmdata : BitmapData ;
var tf:TextField = new TextField();
var rect:Rectangle = new Rectangle(0,0,24,24);
var matrix:Matrix = new Matrix(1,0,0,1,0,0);
var tx:int = 0;
var ty:int = 0;
for(var i:int = 0 ; i < 32 ; i++){
tx = (i%8) * 24;
ty = int(i/8) * 24;
//rect = new Rectangle( tx , ty ,48, 48);
matrix = new Matrix(1,0,0,1,-tx,-ty);
// matrix.tx = -int(i%24) * 24;
// matrix.ty = -int(i/24) * 24;
// rect.y = int(i/24) * 24;
// rect.x = (i%24) * 24;
bmdata = new BitmapData(48,48, true, 0x000000 );
bmdata.draw(loader,matrix,null,null,rect);
data[i] = bmdata;
}
mainptr.makeMap();
}
static public function getGraph(num:int):BitmapData {
//要求された番号のbitmapdataを返す関数
if(data.length <= num)
return enpty;
else
return data[0];
//var ret:BitmapData = new BitmapData(24 , 24 , true , 0xFF6666FF );
//return ret;
}
}
//キーボードから入力するためのクラス
class Key{
static public var keyary:Array;
static public function Init():void{
//メンバの初期化
keyary = new Array();
for(var i:int = 0 ; i < 255 ; i++)
keyary[i] = false;
}
static public function keydown(event:KeyboardEvent):void {
keyary[event.keyCode] = true;
}
static public function keyup(event:KeyboardEvent):void {
keyary[event.keyCode] = false
}
//以前のKey.isDownをだいたい再現してる関数
static public function isDown(code:int):Boolean {
return keyary[code];
}
}
//マップを編集するためのカーソルのクラス
class Cursor extends Sprite{
private var mc_parent:Map;
private var icon :MapChip;
private var chipnumber : int;
public function onEnterFrame(event:Event):void{
y = int(stage.mouseY / 24)*24+12;
x = int(stage.mouseX / 24)*24+12;
/*
var cellX:int = int(stage.mouseX / 24);
var cellY:int = int(stage.mouseY / 24);
mc_parent.addBlock(0,0,chipnumber);
mc_parent.addBlock(cellX,cellY,chipnumber);
*/
}
public function onWheel(event:MouseEvent):void{
if(event.delta > 0 ){
chipnumber++;
icon.changeChip(chipnumber);
}
else if(chipnumber > 0){
chipnumber--;
icon.changeChip(chipnumber);
}
}
public function onClick(event:MouseEvent):void{
var cellX:int = int(stage.mouseX / 24);
var cellY:int = int(stage.mouseY / 24);
mc_parent.addBlock(0,0,chipnumber);
mc_parent.addBlock(cellX,cellY,chipnumber);
}
public function Cursor(h_parent :Map){
mc_parent = h_parent;
chipnumber = 4;
icon = new MapChip(chipnumber);
icon.x = -MapChip.chip_width / 2;
icon.y = -MapChip.chip_width / 2;
addChild(icon);
}
}
//二次元のマップのクラス
class Map extends Sprite {
public var cursor:Cursor; //カーソルへの参照
public var map:Array; //マップの形を数字で表す配列
public var block_ins:Array; //各ブロックへの参照を入れておく配列
public var blayer:Sprite;//ブロックを並べるスプライト
public var background:Shape;//背景
public var mychara:Chara;
public var tf:TextField;//テキスト
public function Map(){
//背景を配置
//background = new Shape();
//background.graphics.beginFill(0xCCFFCC);
//background.graphics.drawRect(0,0,465,465);
//addChild(background);
//blocklayer.addChild(tf);
//ブロックレイヤーを配置
blayer = new Sprite();
addChild(blayer);
//var tf:TextField = new TextField();
//tf.text = "texst";
//操作キャラを配置
mychara = new Chara( GraphStrage.getGraph(0) ,this);
addChild(mychara);
//カーソルを配置
cursor = new Cursor(this);
cursor.addEventListener(Event.ENTER_FRAME , cursor.onEnterFrame);
cursor.addEventListener(MouseEvent.MOUSE_WHEEL , cursor.onWheel);
cursor.addEventListener(MouseEvent.MOUSE_DOWN , cursor.onClick);
addChild(cursor);
//デバッグ用テキストを配置
tf = new TextField();
tf.text = "";
addChild(tf);
map = new Array();
block_ins = new Array();
for(var i:int = 0 ; i < 19 ; i++){
map[i] = new Array();
block_ins[i] = new Array();
}
for(i = 0 ; i < 19 ; i++)
for(var j:int = 0 ; j < 19 ; j++)
addBlock(i,j,j>10? j>15? 1: Math.floor(Math.random()*30) :0);
}
public function addBlock(h_x:int , h_y:int , kind:int ):void {
var blk:MapChip;
//このswitchにブロックの種類を追加していく
switch(kind){
case 1:
blk = new Block_Normal();
break;
case 2:
blk = new Block_Ice();
break;
case 3:
blk = new Block_Note();
break;
case 4: //ちくわ
blk = new Block_Normal(4);
break;
case 6:
blk = new Block_Rope();
break;
case 7 : //とげ
blk = new Block_Normal(7);
break;
default:
kind = 0;
blk = new Block(kind);
}
//ブロックを配置
if(block_ins[h_x][h_y] != null)
blayer.removeChild(block_ins[h_x][h_y]);//removeChildする場所を変更するのを忘れてた。
map[h_x][h_y] = kind;
block_ins[h_x][h_y] = blk;
blk.x = h_x * 24;
blk.y = h_y * 24;
//try{
/*
注意:これは応急措置!
ブロックレイヤーに乗せる形にするべき
だったが解決!
*/
blayer.addChild(blk);
// addChildAt(blk,1);
//}
//catch(e:Error)
//{
// tf.text = "エラー";
//}
}
}
//操作キャラのクラス
class Chara extends Sprite{
public var graph : Array;
public var speed : Number;
public var maxspeed : Number;
public var airspeed : Number;
public var jumppower: Number;
public var gravity:Number;
public var bottomgrand:Number;
public var map:Map;
public var cs:CharaState;
public var bmp:Bitmap;
public var tf:TextField;
public var anime:int;
public function Chara(bmd:BitmapData , mptr:Map){
//各種パラメータを初期化
x = 200;
y = 50;
speed = 0.2;
maxspeed = 3;
airspeed = 0.5;
jumppower= 7.5;
gravity = 0.4;
cs = new CharaState();
cs.vx = 0;
cs.vy = 0;
cs.height = 24;
cs.width = 24;
bottomgrand = 465;
map = mptr;
//枠線をかく
var sh : Shape = new Shape();
sh.graphics.lineStyle(0);
sh.graphics.drawRect(0,0,cs.width,cs.height);
this.addChild(sh);
//与えられたビットマップを描画
bmp = new Bitmap(bmd);
this.addChild(bmp);
this.addEventListener(Event.ENTER_FRAME , onEnterFrame);
//デバッグ用パラメータ表示用テキスト
tf = new TextField();
var tformat:TextFormat = new TextFormat();
tformat.font = "_等幅";
tf.defaultTextFormat = tformat;
tf.background = true;
tf.width = 300;
//map.addChild(tf);
}
public function onEnterFrame(event:Event):void{
//キャラクターを動かすところ
x += cs.vx;
y += (cs.vy += gravity);
var str:String;
str = x.toString() + "\n" + y.toString();
tf.text = str;
//地面に足がついている
if(y + 48 > bottomgrand )
{
cs.granding = true;
cs.y = bottomgrand - 24;
cs.vy = 0;
cs.vx = 0;
}
else
{
cs.granding = false;
if(cs.vx >= 1)
cs.vx -= airspeed*0.1;
else if(cs.vx <= -1)
cs.vx += airspeed*0.1;
}
var point_left :int = int( (x) / 24 );
var point_top :int = int( (y) / 24 );
var point_right :int = int( (x + cs.width ) / 24 );
var point_bottom:int = int( (y + cs.height ) / 24 );
point_left = int( (x) / 24 );
point_top = int((y) / 24 );
point_right = int( (x + cs.width ) / 24 );
point_bottom = int( (y + cs.height ) / 24 );
if(map.map[point_right][point_bottom] != 0){
//右下ポイント
cs.y = y;
cs.x = x;
tf.text += "\n右下p";
// 上端からの距離 > 左端からの距離
if( ((cs.y + cs.height) % 24) > ((cs.x + cs.width) % 24)){
if(map.block_ins[point_right-1][point_bottom].blockable == false){
tf.text += "左Hit";
cs.getOtherState(map.block_ins[point_right][point_bottom].f_left(cs));
}
}
else{
if(map.block_ins[point_right][point_bottom - 1].blockable == false){
//上のマスが開いていないと足がかからない
tf.text += "上hit";
cs.getOtherState(map.block_ins[point_right][point_bottom].f_top(cs));
}
}
x = cs.x;
y = cs.y;
}
point_left = int( (x) / 24 );
point_top = int((y) / 24 );
point_right = int( (x + cs.width ) / 24 );
point_bottom = int( (y + cs.height ) / 24 );
if(map.map[point_left][point_bottom] != 0){
//左下ポイント
cs.y = y;
cs.x = x;
tf.text += "\n左下p";
// 下端からの距離 < 左端からの距離
if( 24 - ((cs.y + cs.height) % 24) < cs.x % 24 ){
if(map.block_ins[point_left + 1][point_bottom].blockable == false){
tf.text += "右hit";
cs.getOtherState(map.block_ins[point_left][point_bottom].f_right(cs));
}
}
else{
if(map.block_ins[point_left][point_bottom - 1].blockable == false){
tf.text += "上hit";
cs.getOtherState(map.block_ins[point_left][point_bottom].f_top(cs));
}
}
x = cs.x;
y = cs.y;
}
point_left = int( (x) / 24 );
point_top = int((y) / 24 );
point_right = int( (x + cs.width ) / 24 );
point_bottom = int( (y + cs.height ) / 24 );
if(map.map[point_right][point_top] != 0){
//右上ポイント
cs.y = y;
cs.x = x;
//var pointx = ;
//var pointy = ;
//左端にぶつかるか、下端にぶつかるか
//マスの下端からの距離と左端からの距離を比べて、
//左端からの方が短ければ左Hit
tf.text += "\n右上p";
if(24 - cs.y % 24 > (cs.x + cs.width) % 24){
tf.text += "左hit";
if(map.block_ins[point_right - 1][point_top].blockable == false){
cs.getOtherState(map.block_ins[ point_right ][ point_top ].f_left(cs));
}
}
else{
tf.text += "下hit";
if(map.block_ins[point_right][point_top + 1].blockable == false){
cs.getOtherState(map.block_ins[ point_right ][ point_top ].f_bottom(cs));
}
}
x = cs.x;
y = cs.y;
}
point_left = int( (x) / 24 );
point_top = int((y) / 24 );
point_right = int( (x + cs.width ) / 24 );
point_bottom = int( (y + cs.height ) / 24 );
if(map.map[point_left][point_top] != 0){
//左上ポイント
cs.y = y;
cs.x = x;
tf.text += "\n左上p";
// 上端からの距離 < 左端からの距離
if( (cs.y % 24) < (cs.x % 24)){
tf.text += "右hit";
if(map.block_ins[point_left + 1][point_top].blockable == false){
cs.getOtherState(map.block_ins[point_left][point_top].f_right(cs));
}
}
else{
if(map.block_ins[point_left][point_top + 1].blockable == false){
tf.text += "下hit";
cs.getOtherState(map.block_ins[point_left][point_top].f_bottom(cs));
}
}
x = cs.x;
y = cs.y;
}
key_control();
animetion();
}
private function key_control():void
{
//操作を読み取るところ
if(Key.isDown(67))
{ //C
cs.vx = 0;
cs.vy = -gravity;
if(Key.isDown(40)) //下キー
this.y++;
if(Key.isDown(39)) //右キー
this.x++;
if(Key.isDown(37)) //左キー
this.x--;
if(Key.isDown(38)) //上キー
this.y--;
if(Key.isDown(88))
{
map.scaleX = 2.0;
map.scaleY = 2.0;
}
}
else
{ //普通の操作
if(Key.isDown(40)) //下キー
this.y++;
if(Key.isDown(39)) //右キー
{
//キャラチップが右を向く
bmp.x = 24;
bmp.scaleX = -1;
if(cs.granding)
{
cs.walking = true;
if(cs.vx < maxspeed)
{
this.cs.vx += speed;
}
}
else if(cs.vx < maxspeed)
cs.vx += airspeed;
}
else if(Key.isDown(37)) //左キー
{
//キャラチップが左を向く
bmp.x = 0;
bmp.scaleX = 1;
if(cs.granding)
{
cs.walking = true;
if(cs.vx > -maxspeed)
{
this.cs.vx -= speed;
}
}
else if(cs.vx > -maxspeed)
cs.vx -= airspeed;
}
else
{
cs.walking = false;
}
if(Key.isDown(90) || Key.isDown(38)) //上、Zキー
{
if(cs.granding)
cs.vy = -jumppower;
}
if(Key.isDown(88)) //Xキー
{this.y++;}
}
}
private function animetion():void
{
//状況によってbmp.bitmapdataを書き換えてアニメーションする
if(cs.granding){
if(cs.walking){
switch(anime++){
case 5:
bmp.bitmapData = GraphStrage.data[0];
break;
case 10:
bmp.bitmapData = GraphStrage.data[1];
break;
case 15:
bmp.bitmapData = GraphStrage.data[0];
break;
case 20:
bmp.bitmapData = GraphStrage.data[2];
anime = 0;
break;
}
}
else{
bmp.bitmapData = GraphStrage.data[0];
}
}
else
{
bmp.bitmapData = GraphStrage.data[3];
}
}
}