JavaScriptを使って、Web上でマリオみたいなファミコン風の2Dゲームを開発できるサービスBitmeloを使ってみました!とても楽しく、簡単にゲーム開発を楽しむことができたので、使い方や機能について、ご紹介したいと思います!
Bitmeloとは
Bitomeloは、とても簡単にWeb上で、2Dゲームを開発・公開できるサービスです。画面は、ピクセルアートで作ります。
Bitmeloの公式サイトはこちらです。
どんなゲームを作ることができるのか
デフォルトで入っているゲームは、きのこをとると文字の色が変わったり、はねたりするシンプルなゲームです。アレンジ次第で、マリオみたいなピクセルアートの2Dゲームを作ることができます。
マリオとはほど遠いですが、私もデフォルトのゲームをアレンジして、ゲームを作ってみました。下記の画面をClickして、遊んでみてください。※キャラクターの操作時に、音がでます。
Bitmeloの機能
Bitomeloには、ゲームで使う素材を作るための様々なエディターが備わっており、すぐにでもゲーム開発をスタートすることができます。どのようなエディターがあるのか、またそれぞれの機能をご紹介していきます。
Tile Editor タイルを作成してみよう
ゲームで使用するためのドット絵が作成できるTile Editorです。キャラクターや背景など、すべてこのエディターで作成します。
タイルひとつにつき、ひとつのタイルを登録できる仕組みで、プログラム部分では、IDで表示を出し分けます。

Tilemap Edtor タイルを配置してみよう
作ったタイルを配置するためのTilemap Editorです。 配置したいタイルを選択して、Mapに置いていくだけです。

Sound Editor ゲームの音を作ってみよう
ゲームで使う音楽を作るためのSound Editorです。

Code コードを書いてみよう
プログラムを書くための、Code Edtitorです。実際にキャラクターを動かしたり、素材を配置するには、コードを書くことになります。JavaScriptの基本的なことを理解されている方であれば、簡単に記述することができます。サイドバーにリファレンスが用意されているので、使い方を確認しながら開発を進めることが可能です。

Project ゲームの画面設定や、インポート・エクスポートしてみよう
プロジェクトの画面幅を決めたり、プロジェクトをインポート・エクスポートするための機能です。Export HTML Gameをクリックすると、HTMLにScriptが組み込まれたファイルをダウンロードすることができ、そのままサーバーにアップすればすぐに、ゲームを公開・楽しむことができます。

Introduction ゲームの説明をつけよう
ゲームの説明を表示するための機能です。どんな操作をすると、どのような動きになるのか説明があると親切です。

実際のゲーム画面では、ゲーム画面の下に説明文が表示されます。

Publish 作ったゲームを公開してみよう
作ったゲームをオンライン上で公開するための機能です。ボタンひとつで、全世界に公開することが可能です。

Publishボタンをクリックすると、プロジェクト名(ゲームのタイトル)やどのようなライセンスで公開するのかを選択する画面が表示されます。
規約に同意するチェックボックスにチェックを入れて、Publishボタンを押すと、公開されます。

公開されると、最新のデータ公開日時とプロジェクト名、ゲームのURLが表示されます。

URLにアクセスすると、ゲームのページに飛びます。
私の作ったゲームのURLはこちら https://bitmelo.com/user/mai12345/games/maifirstgame

作ったゲームをすぐに公開して遊べるのは、すごく便利ですし、テンションが上がりますね!
JavaScirptのコードの中身
コードの中身はデフォルトで、こんな感じになってます。キャラクターを表示したり、動かす部分はコードが含まれています。コードを眺めているだけでも、ゲームがどんな風に作られているのか簡単に学ぶことができます。
例えば、これは、きのこを表示する配列。x座標とy座標を設定して、位置を決めます。
const mushrooms = [
{
x: 40,
y: 100,
wasGrabbed: false
},
{
x: 20,
y: 30,
wasGrabbed: false
},
{
x: 120,
y: 50,
wasGrabbed: false
},
{
x: 50,
y: 100,
wasGrabbed: false
}
];
きのこを表示するためのスクリプト。scr.drawTile()という関数が、タイルを表示するためのスクリプトです。これをきのこの配列分、ループ処理しています。
function drawMushrooms() {
mushrooms.forEach( mushroom => {
if ( !mushroom.wasGrabbed ) {
scr.drawTile(
5,
mushroom.x - 8, // center on the position
mushroom.y - 8, // center on the position
0
);
}
} );
}
キャラクターを表示するスクリプト。frameGIDというのが、タイルエディターで作成した際の登録IDです。
// draw the player
let frameGID = 1;
if ( player.isWalking ) {
if ( player.framesSinceWalkStart % 16 < 8 ) {
frameGID = 2;
}
else {
frameGID = 3;
}
}
scr.drawTile(
frameGID,
Math.floor( player.x ) - 8, // center the tile on the position
Math.floor( player.y ) - 8, // center the tile on the position
player.flip
);
}
コードの全体。
// Globals
let inp = null; // input
let scr = null; // screen
let aud = null; // audio
const player = {
x: 100,
y: 50,
speed: 0.5,
isWalking: false,
flip: 0,
framesSinceWalkStart: 0
}
const mushrooms = [
{
x: 40,
y: 100,
wasGrabbed: false
},
{
x: 20,
y: 30,
wasGrabbed: false
},
{
x: 120,
y: 50,
wasGrabbed: false
},
{
x: 50,
y: 100,
wasGrabbed: false
}
];
let numberOfGrabbedMushrooms = 0;
let randomColor = 1;
// initialization
engine.onInit = () => {
inp = engine.input;
scr = engine.screen;
aud = engine.audio;
updateColors();
};
// update loop
engine.onUpdate = () => {
scr.clear( 1 );
scr.drawMap(
0, // originX on map
0, // originY on map
-1, // width
-1, // height
0, // screenX
0, // screenY
0 // tilemap index
);
drawMushrooms();
updatePlayer();
let textMainColor = 2;
if ( numberOfGrabbedMushrooms > 0 ) {
textMainColor = randomColor;
}
let textPositionOffset = 0;
if ( numberOfGrabbedMushrooms > 1 ) {
textPositionOffset = Math.sin( engine.realTimeSinceGameStart * 5 ) * 8;
}
scr.drawText(
'Hello!! My World!',
100,
100 + Math.floor( textPositionOffset ),
textMainColor,
1,
0
);
};
function drawMushrooms() {
mushrooms.forEach( mushroom => {
if ( !mushroom.wasGrabbed ) {
scr.drawTile(
5,
mushroom.x - 8, // center on the position
mushroom.y - 8, // center on the position
0
);
}
} );
}
function updatePlayer() {
let newX = player.x;
let newY = player.y;
let isWalking = false;
if ( inp.left.pressed ) {
newX -= player.speed;
isWalking = true;
player.flip = 1;
}
else if ( inp.right.pressed ) {
newX += player.speed;
isWalking = true;
player.flip = 0;
}
if ( inp.down.pressed ) {
newY -= player.speed;
isWalking = true;
}
else if ( inp.up.pressed ) {
newY += player.speed;
isWalking = true;
}
if ( isWalking ) {
player.framesSinceWalkStart += 1;
}
// play or stop audio
if ( isWalking && !player.isWalking ) {
// started walking
player.framesSinceWalkStart = 0;
let note = bitmelo.Notes.C4;
if ( numberOfGrabbedMushrooms > 1 ) {
note = bitmelo.Notes.C2;
}
else if ( numberOfGrabbedMushrooms > 0 ) {
note = bitmelo.Notes.C3;
}
aud.playInfiniteSound(
0,
note,
0.5,
2
);
}
else if ( !isWalking && player.isWalking ) {
// stopped walking
aud.stopInfiniteSound( 0 );
}
player.isWalking = isWalking;
// make sure we are not colliding with the fence
if (
newX >= 16
&& newX < scr.width - 16
&& newY >= 24
&& newY < scr.height - 16
) {
player.x = newX;
player.y = newY;
}
// check mushroom collisions
for ( let i = 0; i < mushrooms.length; i += 1 ) {
const mushroom = mushrooms[i];
if ( !mushroom.wasGrabbed ) {
const deltaX = Math.abs( player.x - mushroom.x );
const deltaY= Math.abs( player.y - mushroom.y );
const distance = Math.sqrt( deltaX * deltaX + deltaY * deltaY );
// player has grabbed a mushroom
if ( distance <= 12 ) {
mushroom.wasGrabbed = true;
numberOfGrabbedMushrooms += 1;
aud.playSound(
1,
bitmelo.Notes.E3,
48,
0.25,
1
);
}
}
}
// draw the player
let frameGID = 2;
if ( player.isWalking ) {
if ( player.framesSinceWalkStart % 16 < 8 ) {
frameGID = 2;
}
else {
frameGID = 3;
}
}
scr.drawTile(
frameGID,
Math.floor( player.x ) - 8, // center the tile on the position
Math.floor( player.y ) - 8, // center the tile on the position
player.flip
);
}
function updateColors() {
randomColor = Math.floor( Math.random() * 16 ) + 1;
setTimeout( updateColors, 100 );
}
終わりに
以上、ざっくりですが、Bitmiloの機能と使い方を紹介しました。
動きや、キャラクターの表示を変えるには、基礎的なJavaScriptの知識が必要ですが、タイルの作成や、タイルの配置は、お子さんでもできるので、親子で一緒にゲーム作りを楽しんでみるのもおすすめです!