AS3でゲームを作成する その33 | Photoshop CC Tutorials
今回はドット絵職人のアルテミス氏にキャラクターを作成してもらったので
さっそく登場させてみました。

アルテミス職人のサイト:http://ameblo.jp/yukineko-altemis/entry-11050357154.html
参考プログラムサイト:http://mot3601.blog20.fc2.com/blog-entry-928.html

できあがりはこちらをクリック。十字キーで動きます。(BGM、効果音にご注意)

実行結果
$ピック社長のブログ

プログラムはこのようになりました。
Main.as
package 
{
/**
*
*
*/
import flash.display.Sprite;
import flash.events.Event;
import flash.display.Loader;
import flash.events.KeyboardEvent;
import flash.events.MouseEvent;
import flash.system.LoaderContext;
import flash.net.URLRequest;
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.ui.Keyboard;

public class Main extends Sprite
{
private var loader_01:Loader;
private var loader_02:Loader;
private var source_01:BitmapData;
private var source_02:BitmapData;
private var output:BitmapData;
private var display:Display;

public function Main():void
{
if (stage) init();
else addEventListener(Event.ADDED_TO_STAGE, init);
}

private function init(e:Event = null):void
{
removeEventListener(Event.ADDED_TO_STAGE, init);
// entry point
loader_01 = new Loader();
loader_01.contentLoaderInfo.addEventListener("complete", loadingComplete_01);
loader_01.load(new URLRequest("./bomberimage.png"), new LoaderContext(true));

// 画面の準備
output = new BitmapData(465, 465);
var bitmap:Bitmap = new Bitmap(output);
bitmap.x = 0;
bitmap.y = 0;
addChild(bitmap);
}

public function loadingComplete_01(e:Event):void
{
source_01 = new BitmapData(320, 128, true, 0x00000000);
source_01.draw(loader_01);
loadCharImg();
//display = new Display(source_01);
//test.loadImage(source);
//addChild(new Bitmap(source));
//addEventListener(Event.ENTER_FRAME, onEnterFrame);
//stage.addEventListener(MouseEvent.CLICK, onClick);
}

// キャラクター画像の読み込み
public function loadCharImg():void
{
loader_02 = new Loader();
loader_02.contentLoaderInfo.addEventListener("complete", loadingComplete_02);
loader_02.load(new URLRequest("./charImg.png"), new LoaderContext(true));
}

public function loadingComplete_02(e:Event):void
{
source_02 = new BitmapData(96, 256, true, 0x00000000);
source_02.draw(loader_02);
display = new Display(source_01, source_02);
addEventListener(Event.ENTER_FRAME, onEnterFrame);
stage.addEventListener(MouseEvent.CLICK, onClick);
stage.addEventListener(KeyboardEvent.KEY_DOWN,keyDownHandler);
}

private function onEnterFrame(e:Event):void
{
display.bombshori();
display.fireshori();
display.blockshori();
display.render(output);
}

private function onClick(e:MouseEvent):void
{
display.bombset(Math.floor(mouseX / 32), Math.floor(mouseY / 32));
}

// キーダウンイベントの処理
public function keyDownHandler(evt:KeyboardEvent):void
{
if (evt.keyCode == Keyboard.ENTER) {

}else if (evt.keyCode == Keyboard.SPACE) {
//display.bombset(Math.floor(display.charX / 32), Math.floor(display.charY + 32 / 32));
}else if (evt.keyCode == 40) { // 下
display.keyState = 2;
display.charY += 32;
}else if (evt.keyCode == 37) { // 左
display.keyState = 3;
display.charX -= 32;
}else if (evt.keyCode == 38) { // 上
display.keyState = 0;
display.charY -= 32;
}else if (evt.keyCode == 39) { // 右
display.keyState = 1;
display.charX += 32;
}
}

}

}


Display.as
package 
{
/**
*
*
*/
import flash.display.BitmapData;
import flash.geom.Point;
import flash.geom.Rectangle;
import flash.media.Sound;
import flash.net.URLRequest;

public class Display
{
// 効果音
private var url_01:URLRequest = new URLRequest("bomb.mp3");
private var sound_obj_01:Sound = new Sound(url_01);

private var url_02:URLRequest = new URLRequest("setBomb.mp3");
private var sound_obj_02:Sound = new Sound(url_02);

private var url_03:URLRequest = new URLRequest("thema.mp3");
private var sound_obj_03:Sound = new Sound(url_03);

private var tile:Vector.;
private var tile_char:Vector.;
private var charAnimTime:int = 0;
public var charX:int = 0;
public var charY:int = 0;
private var bomb:Vector.;
private var bombx:Vector.;
private var bomby:Vector.;
private var bombanime:Vector.;
private var bombfire:Vector.;
private var bombtime:Vector.;
private var bombfireflag:Vector.;
private var fire:Vector.;
private var firex:Vector.;
private var firey:Vector.;
private var firetime:Vector.;
private var firelength:int = 5;
private var block:Vector.;
private var blockx:Vector.;
private var blocky:Vector.;
private var blockFlag:Array;
private var blocktime:Vector.;

private var chrnum:uint = 0;
private var field:Array = [];
private var fieldCopy:Array = [];

public var keyState:int;

public function Display(source_01:BitmapData, source_02:BitmapData)
{
sound_obj_03.play(0, 0xffffff); // テーマ曲
bomb = new Vector.;
bombx = new Vector.;
bomby = new Vector.;
bombanime = new Vector.;
bombfire = new Vector.;
bombtime = new Vector.;
bombfireflag = new Vector.;
fire = new Vector.;
firex = new Vector.;
firey = new Vector.;
firetime = new Vector.;
block = new Vector.;
blockx = new Vector.;
blocky = new Vector.;
blocktime = new Vector.;
blockFlag = new Array();
tile = new Vector.;
tile.length = 40;
tile.fixed = true;
tile_char = new Vector.;
tile_char.length = 12;
tile_char.fixed = true;

var i:uint;
var j:uint;
field[0] = [26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26];
field[1] = [26, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 26];
field[2] = [26, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 26];
field[3] = [26, 0, 28, 0, 28, 0, 28, 0, 28, 0, 28, 0, 26];
field[4] = [26, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 26];
field[5] = [26, 0, 28, 0, 28, 0, 28, 0, 28, 0, 28, 0, 26];
field[6] = [26, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 26];
field[7] = [26, 0, 28, 0, 28, 0, 28, 0, 28, 0, 28, 0, 26];
field[8] = [26, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 26];
field[9] = [26, 0, 28, 0, 28, 0, 28, 0, 28, 0, 28, 0, 26];
field[10] = [26, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 26];
field[11] = [26, 0, 28, 0, 28, 0, 28, 0, 28, 0, 28, 0, 26];
field[12] = [26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26];

for (i = 0; i < field.length; i++ ) {
fieldCopy[i] = new Array();
blockFlag[i] = new Array();
for (j = 0; j < field[i].length; j++) {
var ran:int = Math.random() * 10;
// 0,29,28は地面(爆弾設置可)
if (field[i][j] == 0 || field[i][j] == 29 || field[i][j] == 28) {
if (ran > 5) {
fieldCopy[i][j] = field[i][j];
field[i][j] = 27; // 27はレンガ
blockFlag[i][j] = false;
}else {
fieldCopy[i][j] = field[i][j];
}
}else {
fieldCopy[i][j] = field[i][j];
}
}
}

for (i = 0; i < 40; i++) {
tile[i] = new BitmapData(32, 32);
}
//tile[0].setPixel(3, 3, 0x000000);

for (j = 0; j < 4; j++){
for (i = 0; i < 10;i++){
tile[j*10+i].copyPixels(source_01, new Rectangle(i*32, j*32, i*32+32, j*32+32), new Point(0, 0));
}
}

// キャラクター
for (i = 0; i < 12; i++) {
tile_char[i] = new BitmapData(32, 64);
}

var k:int = 0;
var l:int = 64;
for (i = 0; i < 12; i += 3) {
tile_char[i + 0].copyPixels(source_02, new Rectangle( 0, k, 32, l), new Point(0, 0));
tile_char[i + 1].copyPixels(source_02, new Rectangle(32, k, 64, l), new Point(0, 0));
tile_char[i + 2].copyPixels(source_02, new Rectangle(64, k, 96, l), new Point(0, 0));

k += 64;
l += 64;
}
}

public function render(output:BitmapData):void
{
var dx:int;
var dy:int;
var n:int;
var rect:Rectangle = new Rectangle(0, 0, 32, 32);
var anime:int;
output.lock();
// 画面を塗りつぶす
output.fillRect(new Rectangle(0, 0, 465 , 465), 0xffffff);

for (dy = 0; dy < 13;dy++){
for (dx = 0; dx < 13; dx++) {
if (field[dy][dx] == 27) { // レンガなら
output.copyPixels(tile[field[dy][dx]], rect, new Point(dx * 32, dy * 32));
}else {
output.copyPixels(tile[fieldCopy[dy][dx]], rect, new Point(dx*32, dy*32));
//output.copyPixels(tile[field[dy][dx]], rect, new Point(dx*32, dy*32));
}
}
}
// 爆弾のアニメーション
n = bomb.length;
while (n--) {
anime = bombanime[n] % 40;
if (anime >= 0 && anime < 10) { output.copyPixels(tile[2], rect, new Point(bombx[n], bomby[n] ), null, null, true); }
else if (anime >= 10 && anime < 20) { output.copyPixels(tile[3], rect, new Point(bombx[n], bomby[n] ), null, null, true); }
else if (anime >= 20 && anime < 30) { output.copyPixels(tile[4], rect, new Point(bombx[n], bomby[n] ), null, null, true); }
else if (anime >= 30 && anime < 40) { output.copyPixels(tile[3], rect, new Point(bombx[n], bomby[n] ), null, null, true); }
}
// 火のアニメーション
n = fire.length;
while (n--) {
if (firetime[n] > 0 && firetime[n] <= 5 ) { output.copyPixels(tile[fire[n] + 14], rect, new Point(firex[n], firey[n] ), null, null, true ); }
else if (firetime[n] > 5 && firetime[n] <= 10 ) { output.copyPixels(tile[fire[n] + 7 ], rect, new Point(firex[n], firey[n] ), null, null, true ); }
else if (firetime[n] > 10 && firetime[n] <= 15) { output.copyPixels(tile[fire[n] ], rect, new Point(firex[n], firey[n] ), null, null, true ); }
else if (firetime[n] > 15 && firetime[n] <= 20) { output.copyPixels(tile[fire[n] + 7 ], rect, new Point(firex[n], firey[n] ), null, null, true ); }
else if (firetime[n] > 20 ) { output.copyPixels(tile[fire[n] + 14], rect, new Point(firex[n], firey[n] ), null, null, true ); }
}
// ブロックのアニメーション
n = block.length;
while (n--) {
if (blocktime[n] >= 0 && blocktime[n] <= 3 ) { output.copyPixels(tile[38], rect, new Point(blockx[n], blocky[n] ), null, null, true ); }
else if (blocktime[n] > 3 && blocktime[n] <= 6 ) { output.copyPixels(tile[37], rect, new Point(blockx[n], blocky[n] ), null, null, true ); }
else if (blocktime[n] > 6 && blocktime[n] <= 9) { output.copyPixels(tile[36], rect, new Point(blockx[n], blocky[n] ), null, null, true ); }
else if (blocktime[n] > 9 && blocktime[n] <= 11) { output.copyPixels(tile[35], rect, new Point(blockx[n], blocky[n] ), null, null, true ); }
else if (blocktime[n] > 11 && blocktime[n] <= 13 ) { output.copyPixels(tile[34], rect, new Point(blockx[n], blocky[n] ), null, null, true ); }
else if (blocktime[n] > 13 && blocktime[n] <= 15) { output.copyPixels(tile[33], rect, new Point(blockx[n], blocky[n] ), null, null, true ); }
else if (blocktime[n] > 15 && blocktime[n] <= 17) { output.copyPixels(tile[32], rect, new Point(blockx[n], blocky[n] ), null, null, true ); }
else if (blocktime[n] > 17 && blocktime[n] <= 20) { output.copyPixels(tile[31], rect, new Point(blockx[n], blocky[n] ), null, null, true ); }
else if (blocktime[n] > 20 ) { output.copyPixels(tile[30], rect, new Point(blockx[n], blocky[n] ), null, null, true ); }
}

// キャラクターのアニメーション
if (charAnimTime++ > 100000) {
charAnimTime = 0;
}
anime = charAnimTime % 40;

switch(this.keyState) {
case 0: // 上
if (anime >= 0 && anime < 10) { output.copyPixels(tile_char[1], new Rectangle(0, 0, 32, 64), new Point(charX, charY), null, null, true); }
else if (anime >= 10 && anime < 20) { output.copyPixels(tile_char[0], new Rectangle(0, 0, 32, 64), new Point(charX, charY), null, null, true); }
else if (anime >= 20 && anime < 30) { output.copyPixels(tile_char[1], new Rectangle(0, 0, 32, 64), new Point(charX, charY), null, null, true); }
else if (anime >= 30 && anime < 40) { output.copyPixels(tile_char[2], new Rectangle(0, 0, 32, 64), new Point(charX, charY), null, null, true); }
break;

case 1: // 右
if (anime >= 0 && anime < 10) { output.copyPixels(tile_char[4], new Rectangle(0, 0, 32, 64), new Point(charX, charY), null, null, true); }
else if (anime >= 10 && anime < 20) { output.copyPixels(tile_char[3], new Rectangle(0, 0, 32, 64), new Point(charX, charY), null, null, true); }
else if (anime >= 20 && anime < 30) { output.copyPixels(tile_char[4], new Rectangle(0, 0, 32, 64), new Point(charX, charY), null, null, true); }
else if (anime >= 30 && anime < 40) { output.copyPixels(tile_char[5], new Rectangle(0, 0, 32, 64), new Point(charX, charY), null, null, true); }
break;

case 2: // 下
if (anime >= 0 && anime < 10) { output.copyPixels(tile_char[7], new Rectangle(0, 0, 32, 64), new Point(charX, charY), null, null, true); }
else if (anime >= 10 && anime < 20) { output.copyPixels(tile_char[6], new Rectangle(0, 0, 32, 64), new Point(charX, charY), null, null, true); }
else if (anime >= 20 && anime < 30) { output.copyPixels(tile_char[7], new Rectangle(0, 0, 32, 64), new Point(charX, charY), null, null, true); }
else if (anime >= 30 && anime < 40) { output.copyPixels(tile_char[8], new Rectangle(0, 0, 32, 64), new Point(charX, charY), null, null, true); }
break;
case 3: // 左
if (anime >= 0 && anime < 10) { output.copyPixels(tile_char[10], new Rectangle(0, 0, 32, 64), new Point(charX, charY), null, null, true); }
else if (anime >= 10 && anime < 20) { output.copyPixels(tile_char[9], new Rectangle(0, 0, 32, 64), new Point(charX, charY), null, null, true); }
else if (anime >= 20 && anime < 30) { output.copyPixels(tile_char[10], new Rectangle(0, 0, 32, 64), new Point(charX, charY), null, null, true); }
else if (anime >= 30 && anime < 40) { output.copyPixels(tile_char[11], new Rectangle(0, 0, 32, 64), new Point(charX, charY), null, null, true); }
break;
}

output.unlock();
chrnum = (chrnum + 1) % 30;
}

public function bombset(bx:int, by:int):void
{
if(bx<12 && by<12){
if (field[by][bx] == 0 || field[by][bx] == 29 || field[by][bx] == 28) {
sound_obj_02.play();
bomb.push(1);
bombx.push(bx * 32); //爆弾の座標
bomby.push(by * 32);
bombanime.push(0); //爆弾のアニメーション用
bombtime.push(128); //爆弾が爆発するまでの時間
bombfire.push(firelength); //火の長さ
bombfireflag.push(0);
field[by][bx] = 2;
}
}
}

public function bombshori():void
{
var i:int = bomb.length;
while(i--){
bombanime[i] = (bombanime[i] + 1) % 160;
bombtime[i]--;
if (bombtime[i] < 0) {
sound_obj_01.play();
var cx:int = Math.floor(bombx[i] / 32);
var cy:int = Math.floor(bomby[i] / 32);
makefire(cx, cy,i);
}
}
}

public function makefire(cx:int, cy:int, i:int):void
{
var count:int;
var n:int;
var cx2:int;
var cy2:int;
fire.push(5);
firex.push(cx*32);
firey.push(cy*32);
firetime.push(25);
cx2 = cx;
cy2 = cy;
//上方向の火
if ((bombfireflag[i] & 4) == 0) {
cy2--;
count = 0;
while (field[cy2][cx2] == 0 && count < firelength || field[cy2][cx2] == 29 && count < firelength || field[cy2][cx2] == 28 && count < firelength || field[cy2][cx2] == 27) {
if (count == firelength - 1 || field[cy2][cx2] == 27) {
fire.push(10);
firex.push(cx2 * 32);
firey.push(cy2 * 32);
firetime.push(25);
count++;
if (field[cy2][cx2] == 27 && blockFlag[cy2][cx2] == false) { // 27はブロック
blockFlag[cy2][cx2] = true;
block.push(1);
blockx.push(cx2 * 32);
blocky.push(cy2 * 32);
blocktime.push(25);
}
//field[cy2][cx2] = fieldCopy[cy2][cx2]; // ブロックを消す
break;
} else {
fire.push(7);
firex.push(cx2 * 32);
firey.push(cy2 * 32);
firetime.push(25);
count++;
}
cy2--;
}
if (field[cy2][cx2] == 2) { //火が爆弾にあたった
n = bomb.length;
while (n--) {
if (cx2 == Math.floor(bombx[n] / 32) && cy2 == Math.floor(bomby[n] / 32)) {
bombtime[n] = 0;
bombfireflag[n] = bombfireflag[n] | 8;
}
}
}
}
//下方向の火
cx2 = cx;
cy2 = cy;
if ((bombfireflag[i] & 8) == 0) {
cy2++;
count = 0;
while (field[cy2][cx2] == 0 && count < firelength || field[cy2][cx2] == 29 && count < firelength || field[cy2][cx2] == 28 && count < firelength || field[cy2][cx2] == 27) {
if (count == firelength - 1 || field[cy2][cx2] == 27) {
fire.push(11);
firex.push(cx2 * 32);
firey.push(cy2 * 32);
firetime.push(25);
count++;
if (field[cy2][cx2] == 27 && blockFlag[cy2][cx2] == false ) { // 27はブロック
blockFlag[cy2][cx2] = true;
block.push(1);
blockx.push(cx2 * 32);
blocky.push(cy2 * 32);
blocktime.push(25);
}
//field[cy2][cx2] = fieldCopy[cy2][cx2]; // ブロックを消す
break
} else {
fire.push(7);
firex.push(cx2 * 32);
firey.push(cy2 * 32);
firetime.push(25);
count++;
}
cy2++;
}
if (field[cy2][cx2] == 2) { //火が爆弾にあたった
n = bomb.length;
while (n--) {
if (cx2 == Math.floor(bombx[n] / 32) && cy2 == Math.floor(bomby[n] / 32)) {
bombtime[n] = 0;
bombfireflag[n] = bombfireflag[n] | 4;
}
}
}
}
//右方向の火
cx2 = cx;
cy2 = cy;
if ((bombfireflag[i] & 1) == 0) {
cx2++;
count = 0;
while (field[cy2][cx2] == 0 && count < firelength || field[cy2][cx2] == 29 && count < firelength || field[cy2][cx2] == 28 && count < firelength || field[cy2][cx2] == 27 && count < firelength) {
if (count == firelength - 1 || field[cy2][cx2] == 27) { // 27はレンガ
fire.push(9);
firex.push(cx2 * 32);
firey.push(cy2 * 32);
firetime.push(25);
if (field[cy2][cx2] == 27 && blockFlag[cy2][cx2] == false) { // 27はブロック
blockFlag[cy2][cx2] = true;
block.push(1);
blockx.push(cx2 * 32);
blocky.push(cy2 * 32);
blocktime.push(25);
}
count++;
//field[cy2][cx2] = fieldCopy[cy2][cx2]; // ブロックを消す
break;
} else {
fire.push(6);
firex.push(cx2 * 32);
firey.push(cy2 * 32);
firetime.push(25);
count++;
}
cx2++;
}

if (field[cy2][cx2] == 2) { //火が爆弾にあたった
n = bomb.length;
while (n--) {
if (cx2 == Math.floor(bombx[n] / 32) && cy2 == Math.floor(bomby[n] / 32)) {
bombtime[n] = 0;
bombfireflag[n] = bombfireflag[n] | 2;
}
}
}
}
//左方向の火
cx2 = cx;
cy2 = cy;
if ((bombfireflag[i] & 2) == 0) {
cx2--;
count = 0;
while (field[cy2][cx2] == 0 && count < firelength || field[cy2][cx2] == 29 && count < firelength || field[cy2][cx2] == 28 && count < firelength || field[cy2][cx2] == 27) {
if (count == firelength - 1 || field[cy2][cx2] == 27) {
fire.push(8);
firex.push(cx2 * 32);
firey.push(cy2 * 32);
firetime.push(25);
if (field[cy2][cx2] == 27 && blockFlag[cy2][cx2] == false) { // 27はブロック
blockFlag[cy2][cx2] = true;
block.push(1);
blockx.push(cx2 * 32);
blocky.push(cy2 * 32);
blocktime.push(25);
}
//field[cy2][cx2] = fieldCopy[cy2][cx2]; // ブロックを消す
count++;
break;
} else {
fire.push(6);
firex.push(cx2 * 32);
firey.push(cy2 * 32);
firetime.push(25);
count++;
}
cx2--;
}
if (field[cy2][cx2] == 2) { //火が爆弾にあたった
n = bomb.length;
while (n--) {
if (cx2 == Math.floor(bombx[n] / 32) && cy2 == Math.floor(bomby[n] / 32)) {
bombtime[n] = 0;
bombfireflag[n] = bombfireflag[n] | 1;
}
}
}
}
//爆弾を消す
field[cy][cx] = 0;
bomb.splice(i,1);
bombx.splice(i,1);
bomby.splice(i,1);
bombanime.splice(i,1);
bombtime.splice(i,1);
bombfire.splice(i, 1);
bombfireflag.splice(i, 1);
}

public function fireshori():void
{
var n:int = fire.length;
while (n--) {
firetime[n]--;
if (firetime[n] < 0) {
//火を消す
fire.splice(n, 1);
firex.splice(n,1);
firey.splice(n,1);
firetime.splice(n,1);
}
}
}

public function blockshori():void
{
var n:int = block.length;
while (n--) {
blocktime[n]--;
if (blocktime[n] < 0) {
//火を消す
var cx:int = Math.floor(blockx[n] / 32);
var cy:int = Math.floor(blocky[n] / 32);
field[cy][cx] = fieldCopy[cy][cx]; // ブロックを消す
blockFlag[cy][cx] = false;
block.splice(n, 1);
blockx.splice(n,1);
blocky.splice(n,1);
blocktime.splice(n,1);
}
}
}
}

}


BGM,効果音をお借りしたサイトです。
http://www.skipmore.com/
http://koukaongen.com/cgi/se_search/herodb.cgi?table=sound&search=%94%9A%94%AD

このゲームに使用されている素材です。
$ピック社長のブログ
$ピック社長のブログ

画像を使用する場合はドット絵専門家のアルテミス職人の許可をもらってください。

アルテミス職人のサイト:
↓は爆弾の素材です。
http://ameblo.jp/yukineko-altemis/entry-11016380157.html
↓は壁と炎の素材です。
http://secret.ameba.jp/yukineko-altemis/amemberentry-11041239304.html
↓は壁、地面、レンガの素材です。
http://ameblo.jp/yukineko-altemis/entry-11045283691.html
↓はブロックの素材です。
http://ameblo.jp/yukineko-altemis/theme-10008493007.html
↓はキャラクターの素材です。
http://ameblo.jp/yukineko-altemis/entry-11050357154.html