最近学习了一下html5的canvas技术,做了space bowling的小游戏练手。为cocos2d-html5做点准备。
only备份代码。
index.htm
<!DOCTYPE html>
<html>
<head>
<title>Space Bowing</title>
<meta charset="utf-8">
<link href = "game.css" rel = "stylesheet" type = "text/css">
<script type = "text/javascript" src="http://libs.baidu.com/jquery/1.9.0/jquery.js"></script>
<script type = "text/javascript" src="game.js"></script>
</head>
<body>
<div id = "game">
<div id = "gameUI">
<div id = "gameIntro">
<h1>Space bowing</h1>
<p>This is an awesome game.</p>
<p><a id="gamePlay" class="button" href="">Play</a></p>
</div>
<div id = "gameStats">
<p>Asteroids :<span id = "gameRemaining"></span></p>
<p>Clicks :<span class = "gameScore"></span></p>
<p><a class = "gameReset" href = "">Reset</a></p>
</div>
<div id = "gameComplete">
<h1>You Win!</h1>
<p>Congratulations, you completed the game in <span class = "gameScore"></span> clicks.</p>
<p><a class = "gameReset button" href = "">Play again</a></p>
</div>
</div>
<canvas id = "gameCanvas" widrh = "350" height = "600">
<!-->
</canvas>
</div>
</body>
</html>
game.css
/* CSS Document */
* {margin: 100; padding: 0;}
html, body {height: 100%; width: 100%;}
canvas {display: block;}
body {
background: #000;
color: #fff;
font-family: Verdana, Arial, sans-serif;
font-size: 18px;
}
h1 {
font-size: 30px;
}
p {
margin: 0 20px;
}
a {
color: #fff;
text-decoration: none;
}
a:hover {
text-decoration: underline;
}
a.button {
background: #185da8;
border-radius: 5px;
display: block;
font-size: 30px;
margin: 40px 0 0 45px;
padding: 10px;
width: 200px;
}
a.button: hover {
background: #2488f5;
color: #fff
text-decoration: none;
}
#game {
heigth: 600px;
left: 50%;
margin: -350px 0 0 -175px;
position: relative;
top: 50%;
width: 350px;
}
#gameCanvas {
background: #001022;
}
#gameUI {
height: 600px;
position: absolute;
width: 350px;
}
#gameIntro, #gameComplete {
background: rgba(0, 0, 0, 0.5);
margin-top: 100px;
padding: 40px 0;
text-align: center;
}
#gameStats {
font-size: 14px;
margin: 20px 0;
}
#gameStats .gameReset {
margin: 20px 60px 0 0;
position: absolute;
right: 0;
top: 0;
}
game.js
// JavaScript Document
$(document).ready(function() {
var canvas = $("#gameCanvas");
var context = canvas.get(0).getContext("2d");
var canvasWidth = canvas.width();
var canvasHeight = canvas.height();
var playGame;
var score;
var asteroids;
var player;
var playerOriginalX;
var playerOriginalY;
var playerSelected;
var playerMaxAbsVelocity;
var playerVelocityDampener;
var powerX;
var powerY;
var platformX;
var platformY;
var platformOuterRadius;
var platformInnerRadius;
var ui = $("#gameUI");
var uiIntro = $("#gameIntro");
var uiStats = $("#gameStats");
var uiComplete = $("#gameComplete");
var uiPlay = $("#gamePlay");
var uiReset = $(".gameReset");
var uiRemaining = $("#gameRemaining");
var uiScore = $(".gameScore");
var Asteroid = function(x, y, radius, mass, friction)
{
this.x = x;
this.y = y;
this.radius = radius;
this.mass = mass;
this.friction = friction;
this.vX = 0;
this.vY = 0;
this.player = false;
}
function resetPlayer() {
player.x = playerOriginalX;
player.y = playerOriginalY;
player.vX = 0;
player.vY = 0;
}
function startGame() {
uiScore.html("0");
uiStats.show();
platGame = false;
platformX = canvasWidth/2;
platformY = 150;
platformOuterRadius = 100;
platformInnerRadius = 75;
asteroids = new Array();
playerSelected = false;
playerMaxAbsVelocity = 30;
playerVelocityDampener = 0.3;
powerX = -1;
powerY = -1;
score = 0;
var pRadius = 15;
var pMass = 10;
var pFriction = 0.97;
playerOriginalX = canvasWidth/2;
playerOriginalY = canvasHeight-150;
player = new Asteroid(playerOriginalX, playerOriginalY, pRadius, pMass, pFriction);
player.player = true;
asteroids.push(player);
var outerRing = 8;
var ringCount = 3;
var ringSpacing = (platformInnerRadius/(ringCount-1));
for(var r=0; r<ringCount; r++) {
var currentRing = 0;
var angle = 0;
var ringRadius = 0;
if(r == ringCount-1) {
currentRing = 1;
} else {
currentRing = outerRing - (r*3);
angle = 360/currentRing;
ringRadius = platformInnerRadius-(ringSpacing*r);
};
for(var a=0; a<currentRing; a++)
{
var x = 0;
var y = 0;
if(r == ringCount-1)
{
x = platformX;
y = platformY;
} else {
x = platformX + (ringRadius*Math.cos((angle*a)*(Math.PI/180)));
y = platformY + (ringRadius*Math.sin((angle*a)*(Math.PI/180)));
var radius = 10;
var mass = 5;
var friction = 0.95;
asteroids.push(new Asteroid(x, y, radius, mass, friction));
};
};
uiRemaining.html(asteroids.length-1);
};
$(window).mousedown(function(e) {
if(!playerSelected && player.x == playerOriginalX && player.y == playerOriginalY) {
var canvasOffset = canvas.offset();
var canvasX = Math.floor(e.pageX - canvasOffset.left);
var canvasY = Math.floor(e.pageY - canvasOffset.top);
if(!playGame) {
playGame = true;
animate();
};
var dX = player.x - canvasX;
var dY = player.y - canvasY;
var distance = Math.sqrt((dX*dX)+(dY*dY));
var padding = 5;
if(distance < player.radius+padding) {
powerX = player.x;
powerY = player.y;
playerSelected = true;
};
};
});
$(window).mousemove(function(e) {
if(playerSelected) {
var canvasOffset = canvas.offset();
var canvasX = Math.floor(e.pageX - canvasOffset.left);
var canvasY = Math.floor(e.pageY - canvasOffset.top);
var dX = canvasX - player.x;
var dY = canvasY - player.y;
var distance = Math.sqrt((dX*dX)+(dY*dY));
if(distance*playerVelocityDampener < playerMaxAbsVelocity) {
powerX = canvasX;
powerY = canvasY;
} else {
var ratio = playerMaxAbsVelocity/(distance*playerVelocityDampener);
powerX = player.x + (dX*ratio);
powerY = player.y + (dY*ratio);
};
};
});
$(window).mouseup(function(e) {
if(playerSelected) {
var dX = powerX - player.x;
var dY = powerY - player.y;
player.vX = -(dX * playerVelocityDampener);
player.vY = -(dY * playerVelocityDampener);
uiScore.html(++score);
};
playerSelected = false;
powerX = -1;
powerY = -1;
});
animate();
};
function init() {
uiStats.hide();
uiComplete.hide();
uiPlay.click(function(e) {
e.preventDefault();
uiIntro.hide();
startGame();
});
uiReset.click(function(e) {
e.preventDefault();
uiComplete.hide();
startGame();
});
};
function animate() {
context.clearRect(0, 0, canvasWidth, canvasHeight);
context.fillStyle = "rgb(100, 100, 100)";
context.beginPath();
context.arc(platformX, platformY, platformOuterRadius, 0, Math.PI*2, true);
context.closePath();
context.fill();
if(playerSelected) {
context.strokeStyle = "rgb(255, 255, 255)";
context.lineWidth = 3;
context.beginPath();
context.moveTo(player.x, player.y);
context.lineTo(powerX, powerY);
context.closePath();
context.stroke();
}
context.fillStyle = "rgb(255, 255, 255)";
var deadAsteroids = new Array();
var asteroidsLength = asteroids.length;
for(var i=0; i<asteroidsLength; i++) {
var tmpAsteroid = asteroids[i];
for(var j=i+1; j<asteroidsLength; j++) {
var tmpAsteroidB = asteroids[j];
var dX = tmpAsteroidB.x - tmpAsteroid.x;
var dY = tmpAsteroidB.y - tmpAsteroid.y;
var distance = Math.sqrt((dX*dX)+(dY*dY));
if(distance < tmpAsteroidB.radius + tmpAsteroid.radius) {
var angle = Math.atan2(dY, dX);
var sine = Math.sin(angle);
var cosine = Math.cos(angle);
var x = 0;
var y = 0;
var xB = dX*cosine + dY*sine;
var yB = dY*cosine - dX*sine;
var vX = tmpAsteroid.vX * cosine + tmpAsteroid.vY * sine;
var vY = tmpAsteroid.vY * cosine - tmpAsteroid.vX * sine;
var vXb = tmpAsteroidB.vX * cosine + tmpAsteroidB.vY * sine;
var vYb = tmpAsteroidB.vY * cosine - tmpAsteroidB.vX * sine;
var vTotal = vX - vXb;
vX = ((tmpAsteroid.mass - tmpAsteroidB.mass) * vX + 2 * tmpAsteroidB.mass * vXb) / (tmpAsteroid.mass + tmpAsteroidB.mass);
vXb = vTotal + vX;
xB = x + (tmpAsteroid.radius + tmpAsteroidB.radius);
tmpAsteroid.x = tmpAsteroid.x + (y * cosine - y * sine);
tmpAsteroid.y = tmpAsteroid.y + (y * cosine + x * sine);
tmpAsteroidB.x = tmpAsteroid.x + (xB * cosine - yB * sine);
tmpAsteroidB.y = tmpAsteroid.y + (yB * cosine + xB * sine);
tmpAsteroid.vX = vX * cosine - vY * sine;
tmpAsteroid.vY = vY * cosine + vX * sine;
tmpAsteroidB.vX = vXb * cosine - vYb * sine;
tmpAsteroidB.vY = vYb * cosine + vXb * sine;
};
};
tmpAsteroid.x += tmpAsteroid.vX;
tmpAsteroid.y += tmpAsteroid.vY;
if (Math.abs(tmpAsteroid.vX) > 0.1) {
tmpAsteroid.vX *= tmpAsteroid.friction;
} else {
tmpAsteroid.vX = 0;
};
if (Math.abs(tmpAsteroid.vY) > 0.1) {
tmpAsteroid.vY *= tmpAsteroid.friction;
} else {
tmpAsteroid.vY = 0;
};
if (!tmpAsteroid.player) {
var dXp = tmpAsteroid.x - platformX;
var dYp = tmpAsteroid.y - platformY;
var distanceP = Math.sqrt((dXp*dXp)+(dYp*dYp));
if (distanceP > platformOuterRadius) {
// Kill asteroid
if (tmpAsteroid.radius > 0 && tmpAsteroid != player) {
tmpAsteroid.radius -= 1;
} else {
deadAsteroids.push(tmpAsteroid);
};
};
};
if (player.x != playerOriginalX && player.y != playerOriginalY) {
if (player.vX == 0 && player.vY == 0) {
resetPlayer();
} else if (player.x+player.radius < 0) {
resetPlayer();
} else if (player.x-player.radius > canvasWidth) {
resetPlayer();
} else if (player.y+player.radius < 0) {
resetPlayer();
} else if (player.y-player.radius > canvasHeight) {
resetPlayer();
};
};
context.beginPath();
context.arc(tmpAsteroid.x, tmpAsteroid.y, tmpAsteroid.radius, 0, Math.PI*2, true);
context.closePath();
context.fill();
};
var deadAsteroidsLength = deadAsteroids.length;
if (deadAsteroidsLength > 0) {
for (var di = 0; di < deadAsteroidsLength; di++) {
var tmpDeadAsteroid = deadAsteroids[di];
asteroids.splice(asteroids.indexOf(tmpDeadAsteroid), 1);
};
var remaining = asteroids.length-1; // Remove player from asteroid count
uiRemaining.html(remaining);
if (remaining == 0) {
// Winner!
playGame = false;
uiStats.hide();
uiComplete.show();
// Reset event handlers
$(window).unbind("mousedown");
$(window).unbind("mouseup");
$(window).unbind("mousemove");
};
};
if(playGame) {
setTimeout(animate, 33);
};
};
init();
});
这里有别人发布的这个demo的展示,还提供了源码。