やっぱりゲームを作るのは楽しいな〜と、つぶやいている、ユゲタです。
gameを構築するイメージがまあまあ見えてきたんですが、少し規模の大きいgameを作る時に、
フレームワークを使ってgameを作ってもいいんですが、できるだけ無駄とブラックボックス箇所を無くしたいので、
フルスクラッチでcanvasを使って構築をしたいと思った時に、いろいろなライブラリが必要になる事もイメージできます。
そんなライブラリを作り込んで行きたいと思って、小さなゲームプログラムを作り重ねていき、最終的に自分ライブラリを作ってみたいと思います。
ブログでは、そんなプログラムの解説をしつつ、Githubで都度のバージョンを公開して行く予定です。
本日のIT謎掛け
「ゲームライブラリ」と、かけまして・・・
「公園の遊具」と、ときます。
そのココロは・・・
遊ぶ時に、無いとまあまあ困るもの。
本日の目的
以前に作った三目並べのcanvasライブラリを参照しつつ、データ管理や、表示まわりの効率的な書き方などがまとまっていないので、とりあえず、今回はまだ手を付けていなかった、アニメーションに関するかんたんなライブラリを作ってみたいと思います。
そこで、BASICを学習した時の一番最初に作った「壁打ちテニス」にTRYします。
仕様は、三方壁に囲まれたbox内で直線的に動くボールを、手前のラケット(棒)で、返すだけですが、以下のような処理が必要になります。
・基本描画処理
・開始時の「start」ボタンのクリックイベント処理
・ボールと、ラケットが動くアニメーション描画処理(全体書き換え)
・マウス動作によるラケット移動
・ボールが壁に当たって跳ね返る当たり判定
・ボールがラケットに当たって跳ね返るコリジョン処理
・ボールが画面外に言ってしまった時のGameOver処理
これを簡易仕様として、構築していきます。
基本描画処理
まず始めに、基本の画面表示をしてみます。
画面サイズを決めて、3方の壁の表示です。
初期構築という事で、htmlも含めたソースコードも合わせて掲載しておきます。
ソースコード
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>TicTacToe</title>
<style>
#mycanvas{
display:block;
margin:10px auto;
}
</style>
<script src="common.js"></script>
</head>
<body>
<canvas id="mycanvas">not canvas</canvas>
</body>
</html>
(function(){
var __options = {
canvas : "#mycanvas",
width : 400,
height : 600,
wall : { w : 400 , h : 600 , color_stroke : "transparent" , color_fill : "#382B8C" , size : 20 },
ball : { r : 10 , color_stroke : "transparent" , color_fill : "#F2B5A7" },
bar : { w: 50 , h: 10 , color_stroke : "transparent" , color_fill : "#958ABF" },
$:0
};
var MAIN = function(){
if(!this.check()){
alert("htmlに指定のcanvasがありません。");
return;
}
this.init();
this.draw();
};
MAIN.prototype.getCanvas = function(){
if(typeof this.canvas === "undefined"){
this.canvas = document.querySelector(__options.canvas);
}
return this.canvas;
};
MAIN.prototype.getContext = function(){
if(typeof this.ctx === "undefined"){
var canvas = this.getCanvas();
if(!canvas){return null;}
this.ctx = canvas.getContext("2d");
}
return this.ctx;
};
MAIN.prototype.check = function(){
var ctx = this.getContext();
if(ctx){
return true;
}
else{
return false;
}
};
MAIN.prototype.init = function(){
// 画面サイズ調整
var canvas = this.canvas;
canvas.setAttribute("width" , __options.wall.w);
canvas.setAttribute("height" , __options.wall.h);
};
MAIN.prototype.draw = function(){
this.draw_wall();
this.draw_bar();
this.draw_ball();
};
MAIN.prototype.draw_wall = function(){
var ctx = this.ctx;
ctx.strokeStyle = __options.wall.color_stroke;
ctx.strokeWidth = __options.wall.color_stroke === "transparent" ? 0 : 1;
ctx.fillStyle = __options.wall.color_fill;
ctx.beginPath();
ctx.moveTo(0,0);
ctx.lineTo(__options.wall.w , 0);
ctx.lineTo(__options.wall.w , __options.wall.h);
ctx.lineTo(__options.wall.w - __options.wall.size , __options.wall.h);
ctx.lineTo(__options.wall.w - __options.wall.size , __options.wall.size);
ctx.lineTo(__options.wall.size , __options.wall.size);
ctx.lineTo(__options.wall.size , __options.wall.h);
ctx.lineTo(0 , __options.wall.h);
ctx.lineTo(0 , 0);
ctx.stroke();
ctx.fill();
};
MAIN.prototype.draw_bar = function(){
var ctx = this.ctx;
ctx.strokeStyle = __options.bar.color_stroke;
ctx.strokeWidth = __options.bar.color_stroke === "transparent" ? 0 : 1;
ctx.fillStyle = __options.bar.color_fill;
ctx.fillRect(__options.wall.size + 10 , __options.wall.h - __options.bar.h - 30 , __options.bar.w , __options.bar.h);
};
MAIN.prototype.draw_ball = function(){
var ctx = this.ctx;
ctx.strokeStyle = __options.ball.color_stroke;
ctx.strokeWidth = __options.ball.color_stroke === "transparent" ? 0 : 1;
ctx.fillStyle = __options.ball.color_fill;
ctx.beginPath();
ctx.arc(__options.wall.w / 2, __options.wall.h / 2, __options.ball.r, 0, Math.PI * 2);
ctx.fill();
};
var LIB = function(){};
LIB.prototype.event = function(target, mode, func , flg){
flg = (flg) ? flg : false;
if (target.addEventListener){target.addEventListener(mode, func, flg)}
else{target.attachEvent('on' + mode, function(){func.call(target , window.event)})}
};
LIB.prototype.construct = function(){
switch(document.readyState){
case "complete" : new MAIN();break;
case "interactive" : this.event(window , "DOMContentLoaded" , (function(){new MAIN()}).bind(this));break;
default : this.event(window , "load" , (function(){new MAIN()}).bind(this));break;
}
};
new LIB().construct();
})();
Github
https://github.com/yugeta/game_block
今回は初期表示のみのバージョンなので、あまり面白くないですが、今後バージョンアップさせていく予定なので、楽しんでもらえる方は引き続き読んでくださいませ。
0 件のコメント:
コメントを投稿