markdown W3Cx的Game / EdX JavaScript入门课程/
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了markdown W3Cx的Game / EdX JavaScript入门课程/相关的知识,希望对你有一定的参考价值。
#myCanvas {
border: 1px solid black;
z-index: 1;
position: relative;
left: 50%;
transform: translateX(-50%);
}
input {
z-index: 2;
}
html, body {
width: 100%;
}
.container {
width: 100%;
}
.row {
width: 100%;
height: auto;
}
.row::after {
content: "";
clear: both;
display: table;
}
[class*="col-"] {
width: 100%;
}
@media only screen and (min-width: 768px) {
.col-1-2 {
width: 50%;
height: 100%;
float: left;
}
}
/**************TABLE***********/
table, form {
position: absolute;
left: 50%;
/* top: 50%; */
transform: translateX(-50%);
z-index: 1000;
margin-top: 80px;
}
caption, th {
padding: 20px;
}
td {
padding: 10px;
}
caption {
background-color: #ffff00;
font-weight: bold;
}
table, tr, th, td {
border: 1px solid #ffffff;
border-collapse: collapse;
}
th {
background-color:#99ff33;
}
td {
text-align: center;
}
#table tr:nth-child(even){
background-color: #f2f2f2;
}
#table tr:hover {
background-color: #ddd;
}
var canvas, ctx, w, h;
var bullets = [];
var balls = [];
var numberOfBalls = 10;
var index = 0;
var numberOfGoodBalls = 0;
var goodBallsEaten = 0;
var wrongBallsEaten = 0;
var colorToEat = "red";
var oneBallColorToEateCreated = false;
var gameOver = false;
var newLevel = false;
var level = 1;
var speedCoef = 1;
var requestId;
var nowPlayingIndex = 14;
var gameBackgroundIndex;
var newBackground = false;
var mousePosition;
var currentScore = 0;
var numberOfAssetsToLoad = 0;
var player = {
width: 20,
height: 20,
x: 10,
y: 10,
color: "red",
move: function(x, y) {
if(mousePosition !== undefined){
this.x = x;
this.y = y;
}
},
draw: function() {
drawFilledRect(this)
}
}
var assetsToLoadURLs = {
backgroundImage: { url: 'https://mainline.i3s.unice.fr/mooc/SkywardBound/assets/images/background.png' }, // http://www.clipartlord.com/category/weather-clip-art/winter-clip-art/
backgroundImage1: { url: 'http://www.clker.com/cliparts/0/b/0/f/1197119063962204382ryanlerch_grassy_horizon_(gradient).svg.hi.png' },
backgroundImage2: { url: 'http://www.clker.com/cliparts/c/0/1/d/12065578651282111944chelseafan528_Grassy_Scene.svg.hi.png' },
backgroundImage3: { url: 'http://www.clker.com/cliparts/d/8/0/4/12074334211624055201rygle_Creation_Scene_3.svg.hi.png'},
backgroundImage4: { url: 'http://www.clker.com/cliparts/1/3/4/a/1237098635915429223StudioFibonacci_Cartoon_Hillside_with_Butterfly_and_Flowers.svg.hi.png'},
backgroundImage5: { url: 'http://www.clker.com/cliparts/9/d/c/a/1234405664842624179rg1024_grass.svg.hi.png'},
backgroundImage6: { url: 'http://www.clker.com/cliparts/8/6/5/a/1240172473914282518StudioFibonacci_Cartoon_spring.svg.hi.png'},
backgroundImage7: { url: 'http://www.clker.com/cliparts/Z/4/l/A/S/L/background-hi.png'},
logo1: { url: "https://mainline.i3s.unice.fr/mooc/SkywardBound/assets/images/SkywardWithoutBalls.png" },
logo2: { url: "https://mainline.i3s.unice.fr/mooc/SkywardBound/assets/images/BoundsWithoutBalls.png" },
bell: { url: "https://mainline.i3s.unice.fr/mooc/SkywardBound/assets/images/bells.png" },
spriteSheetBunny: { url: 'https://mainline.i3s.unice.fr/mooc/SkywardBound/assets/images/bunnySpriteSheet.png' },
humbug: { url: 'https://mainline.i3s.unice.fr/mooc/SkywardBound/assets/sounds/humbug.mp3', buffer: true, loop: true, volume: 1.0 },
concertino: { url: 'https://mainline.i3s.unice.fr/mooc/SkywardBound/assets/sounds/christmas_concertino.mp3', buffer: true, loop: true, volume: 1.0 },
xmas: { url: 'https://mainline.i3s.unice.fr/mooc/SkywardBound/assets/sounds/xmas.mp3', buffer: true, loop: true, volume: 0.6 },
helperSound : {url: "https://mainline.i3s.unice.fr/mooc/StarWarriors/assets/0B_E4HKbPQZo6MFBDb3JsVFRxN1E.mp3", buffer: false, loop: false, volume: 1.0, type:"sound"},
bombsFly : {url: "https://mainline.i3s.unice.fr/mooc/StarWarriors/assets/0B_E4HKbPQZo6OEFZYzZ3ajNEUVk.mp3", buffer: false, loop: false, volume: 1.0, type:"sound"},
clickCosmos : {url: "https://mainline.i3s.unice.fr/mooc/StarWarriors/assets/0B_E4HKbPQZo6MDFPaFkwdjJSY3M.mp3", buffer: false, loop: false, volume: 1.0, type:"sound"},
clickMenu : {url: "https://mainline.i3s.unice.fr/mooc/StarWarriors/assets/0B_E4HKbPQZo6WTltOXBVaE5vb1E.mp3", buffer: false, loop: false, volume: 1.0, type:"sound"},
littleClick : {url: "https://mainline.i3s.unice.fr/mooc/StarWarriors/assets/0B_E4HKbPQZo6TVROZWxfenIzMUE.mp3", buffer: false, loop: false, volume: 1.0, type:"sound"},
strangerHit : {url: "https://mainline.i3s.unice.fr/mooc/StarWarriors/assets/0B_E4HKbPQZo6WDBhMzJrM29fYXc.mp3", buffer: false, loop: false, volume: 1.0, type:"sound"},
tuk : {url: "https://mainline.i3s.unice.fr/mooc/StarWarriors/assets/0B_E4HKbPQZo6Y0ZYbHZYeU1CNnM.mp3", buffer: false, loop: false, volume: 1.0, type:"sound"},
tukLouder : {url: "https://mainline.i3s.unice.fr/mooc/StarWarriors/assets/0B_E4HKbPQZo6TTRmQ2c0QjBEb1E.mp3", buffer: false, loop: false, volume: 1.0, type:"sound"},
fire : {url: "https://mainline.i3s.unice.fr/mooc/StarWarriors/assets/0B_E4HKbPQZo6blZhMV9FSTl4UHM.mp3", buffer: false, loop: false, volume: 1.0, type:"sound"},
soundCrash : {url: "https://mainline.i3s.unice.fr/mooc/StarWarriors/assets/0B_E4HKbPQZo6X1RLSE9qTGxwYWM.mp3", buffer: false, loop: false, volume: 1.0, type:"sound"},
rocketHit : {url: "https://mainline.i3s.unice.fr/mooc/StarWarriors/assets/0B_E4HKbPQZo6SGpyMDlRYzhydnM.mp3", buffer: false, loop: false, volume: 1.0, type:"sound"},
plop: { url: 'https://mainline.i3s.unice.fr/mooc/SkywardBound/assets/sounds/plop.mp3', buffer: false, loop: false, volume: 1.0 },
};
var loadedAssets;
window.onload = function init(){
canvas = document.querySelector("#myCanvas");
ctx = canvas.getContext('2d');
w = canvas.width;
h = canvas.height;
canvas.addEventListener('mousemove', mouseMoved);
window.addEventListener('keydown', createBullet);
balls = createAllBalls(numberOfBalls);
numberOfGoodBalls = countNumberOfGoodBalls(balls, colorToEat);
loadAssets(startGame);
}
class Ball {
constructor(color) {
this.x = w/2;
this.y = h/2;
this.radius = 5 + 30 * Math.random(); // between 5 and 35
this.speedX = -5 + 10 * Math.random(); // between -5 and + 5
this.speedY = -5 + 10 * Math.random(); // between -5 and + 5
if(!color){
this.color = getRandomColor();
}
else {
this.color = color;
}
}
draw(){
ctx.save();
ctx.fillStyle = this.color;
ctx.translate(this.x, this.y);
ctx.beginPath();
ctx.arc(0,0,this.radius,0,2*Math.PI);
ctx.fill();
ctx.restore();
index = balls.indexOf(this);
testCollisionWithBullets(this, index);
}
move(){
this.x += (this.speedX * speedCoef);
this.y += (this.speedY * speedCoef);
testColisionWithWalls(this);
}
}
class Bullet {
constructor(){
this.width = 5;
this.height = 5;
this.color = "blue";
this.x = player.x + player.width/2 - 5/2;
this.y = player.y;
}
draw(){
if(bullets.length !== 0)
drawFilledRect(this);
}
move(){
if(bullets.length !== 0)
this.y -= 5;
}
}
function startGame(assetsReadyToBeUsed) {
//document.body.innerHTML += "<p>IMAGES, SOUNDS, MUSICS READY TO BE USED!</p>";
// We're ready to use all sounds, images, musics etc
loadedAssets = assetsReadyToBeUsed;
firstStart();
}
function firstStart(){
ctx.clearRect(0,0,w,h);
drawBackground();
ctx.save();
ctx.font = "20px Arial";
ctx.fillText("Press a key to start! Press space to fire!", 20, 70);
ctx.restore();
window.addEventListener('keydown', firstStartGame);
}
function firstStartGame(){
window.removeEventListener('keydown', firstStartGame);
loadedAssets[nowPlayingIndex].play();
mainLoop();
}
function chooseBackgroundIndex(){
var i = Math.floor(Math.random() * 8);
gameBackgroundIndex = i;
}
function playBackgroundMusic(){
loadedAssets[nowPlayingIndex].stop();
var i = Math.floor(Math.random() * (14 - 12 + 1)) + 12;
loadedAssets[i].play();
nowPlayingIndex = i;
}
function countNumberOfGoodBalls(balls, colorToEat) {
var nb = 0;
balls.forEach(function(b) {
if(b.color === colorToEat)
nb++;
});
return nb;
}
function createAllBalls(nb){
var arr = [];
var ballWithColorToEat = new Ball(colorToEat); //Create at least one ball with color to eat;
arr.push(ballWithColorToEat);
for (i = 1; i < nb; i++){
var b = new Ball();
arr.push(b);
}
return arr;
}
function getRandomColor(){
if(oneBallColorToEateCreated) {
var colors = ['red','blue','green','yellow'];
var index = Math.round(Math.random()*(colors.length-1));
var colorChoosen = colors[index];
}
else {
colorChoosen = colorToEat;
oneBallColorToEateCreated = true;
}
return colorChoosen;
}
function createBullet(event){
if(event.keyCode === 32){
var bullet = new Bullet;
bullets.push(bullet);
}
}
function mainLoop(){
if(gameOver || newLevel){
gameOverMenu();
}
else {
ctx.clearRect(0,0,w,h);
drawBackground();
player.draw();
player.move(mousePosition.x, mousePosition.y);
drawBullets();
moveBullets();
drawBalls();
moveBalls();
drawBallNumbers(balls);
requestId = window.requestAnimationFrame(mainLoop);
}
}
function moveBullets(){
bullets.forEach(function(bullet){
bullet.move();
});
}
function drawBullets(){
bullets.forEach(function(bullet){
bullet.draw();
});
}
function drawBalls(){
balls.forEach(function(ball){
ball.draw();
});
}
function moveBalls() {
balls.forEach(function(ball){
ball.move();
});
}
function drawBackground(){
if(!newBackground){
chooseBackgroundIndex();
newBackground = true;
}
ctx.drawImage(loadedAssets[gameBackgroundIndex], 0, 0, w, h);
}
function drawBallNumbers(balls) {
ctx.save();
ctx.font="20px Arial";
currentScore = numberOfBalls - wrongBallsEaten;
if(wrongBallsEaten === 3) {
ctx.fillText("Game Over! You hit tree wrong balls!", 20, 30);
gameOver = true;
} else if(goodBallsEaten === numberOfGoodBalls) {
ctx.fillText("You Win! Final score : " + currentScore,
20, 30);
newLevel = true;
} else {
ctx.fillText("Balls still alive: " + balls.length, 210, 30);
ctx.fillText("Good Balls eaten: " + goodBallsEaten, 210, 50);
ctx.fillText("Wrong Balls eaten: " + wrongBallsEaten, 210, 70);
ctx.fillText("Score: " + currentScore, 210, 90);
}
ctx.fillText("Level: " + level, 20, 390)
ctx.restore();
}
function testColisionWithWalls(b){
if((b.x + b.radius) > w){
b.x = w - b.radius;
b.speedX = - b.speedX;
}
else if((b.x - b.radius) < 0){
b.x = b.radius;
b.speedX = - b.speedX;
}
if((b.y + b.radius) > h){
b.y = h - b.radius;
b.speedY = -b.speedY;
}
else if((b.y - b.radius) < 0){
b.y = b.radius;
b.speedY = -b.speedY;
}
}
function testCollisionWithBullets(b, index) {
for(i=0; i < bullets.length; i++){
if(circRectsOverlap(bullets[i].x, bullets[i].y,
bullets[i].width, bullets[i].height,
b.x, b.y, b.radius)) {
// we remove the element located at index
// from the balls array
// splice: first parameter = starting index
// second parameter = number of elements to remove
if(b.color === colorToEat) {
// Yes, we remove it and increment the score
goodBallsEaten += 1;
} else {
wrongBallsEaten += 1;
}
balls.splice(index, 1);
loadedAssets[24].play();
}
}
}
function circRectsOverlap(x0, y0, w0, h0, cx, cy, r) {
var testX=cx;
var testY=cy;
if (testX < x0) testX=x0;
if (testX > (x0+w0)) testX=(x0+w0);
if (testY < y0) testY=y0;
if (testY > (y0+h0)) testY=(y0+h0);
return (((cx-testX)*(cx-testX)+(cy-testY)*(cy-testY))< r*r);
}
function mouseMoved(evt){
mousePosition = getMousePos(evt, canvas);
}
function getMousePos(evt, canvas){
var rect = canvas.getBoundingClientRect();
return {
x: (evt.clientX - rect.left),
y: (evt.clientY - rect.top)
};
}
function drawFilledRect(r){
ctx.save();
ctx.translate(r.x, r.y);
ctx.fillStyle = r.color;
ctx.fillRect(0,0,r.width,r.height);
ctx.restore();
}
function gameOverMenu(){
playBackgroundMusic();
ctx.save();
ctx.font = "20px Arial";
if (gameOver){
makeTableHightScore(currentScore);
//ctx.fillText("Press enter to restart!", 20, 70);
}
else {
// currentScore += (goodBallsEaten - wrongBallsEaten);
ctx.fillText("Press a key to continue", 20, 70);
level++;
numberOfBalls++;
window.addEventListener('keydown', restart);
}
ctx.restore();
}
function gameOverRestart(evt){
if(evt.keyCode == 13){
window.removeEventListener('keydown', gameOverRestart);
document.querySelector("#nbBalls").value = numberOfBalls;
deleteElement("table");
restart();
}
}
function restart(){
window.removeEventListener('keydown', restart);
goodBallsEaten = 0;
wrongBallsEaten = 0;
balls = createAllBalls(numberOfBalls);
numberOfGoodBalls = countNumberOfGoodBalls(balls, colorToEat);
bullets = [];
gameOver = false;
newLevel = false;
playBackgroundMusic();
newBackground = false;
mainLoop();
}
function changeNbBalls(n){
window.cancelAnimationFrame(requestId);
numberOfBalls = n;
restart();
}
function changePlayerColor(c){
player.color = c;
}
function changeColorToEat(c){
window.cancelAnimationFrame(requestId);
colorToEat = c;
restart();
}
function changeBallSpeed(s){
speedCoef = s;
}
function changeBackgroundSong(value){
loadedAssets[nowPlayingIndex].stop();
var i;
for (var j = 0; j < numberOfAssetsToLoad; j++) {
if (loadedAssets[j].name == value) {
i = j;
loadedAssets[nowPlayingIndex].stop();
loadedAssets[i].play();
nowPlayingIndex = i;
return;
}
}
}
function changeSongVolume(v){
var value = v / 10;
Howler.volume(value);
}
function loadAssets(callback) {
// here we should load the sounds, the sprite sheets etc.
// then at the end call the callback function
loadAssetsUsingHowlerAndNoXhr(assetsToLoadURLs, callback);
}
// You do not have to understand in details the next parts of the code...
// just use the above function
/* ############################
BUFFER LOADER for loading multiple files asyncrhonously. The callback functions is called when all
files have been loaded and decoded
############################## */
function isImage(url) {
return (url.match(/\.(jpeg|jpg|gif|png)$/) != null);
}
function isAudio(url) {
return (url.match(/\.(mp3|ogg|wav)$/) != null);
}
function loadAssetsUsingHowlerAndNoXhr(assetsToBeLoaded, callback) {
var id = 0;
var assetsLoaded = {};
var loadedAssets = 0;
// var numberOfAssetsToLoad = 0;
// define ifLoad function
var ifLoad = function () {
if (++loadedAssets >= numberOfAssetsToLoad) {
callback(assetsLoaded);
}
console.log("Loaded asset " + loadedAssets);
};
// get num of assets to load
for (var name in assetsToBeLoaded) {
numberOfAssetsToLoad++;
}
console.log("Nb assets to load: " + numberOfAssetsToLoad);
for (name in assetsToBeLoaded) {
var url = assetsToBeLoaded[name].url;
console.log("Loading " + url);
if (isImage(url)) {
//assetsLoaded[name] = new Image();
//assetsLoaded[name].onload = ifLoad;
// will start async loading.
//assetsLoaded[name].src = url;
//assetsLoaded[name].id = id;
assetsLoaded[id] = new Image();
assetsLoaded[id].onload = ifLoad;
assetsLoaded[id].name = name;
assetsLoaded[id].src = url;
id++;
} else {
// We assume the asset is an audio file
console.log("loading " + name + " buffer : " + assetsToBeLoaded[name].loop);
// assetsLoaded[name] = new Howl({
assetsLoaded[id] = new Howl({
urls: [url],
buffer: assetsToBeLoaded[name].buffer,
loop: assetsToBeLoaded[name].loop,
autoplay: false,
volume: assetsToBeLoaded[name].volume,
onload: function () {
if (++loadedAssets >= numberOfAssetsToLoad) {
callback(assetsLoaded);
}
console.log("Loaded asset " + loadedAssets);
}
}); // End of howler.js callback
assetsLoaded[id].name = name;
id++;
}
}
}
function makeTableHightScore(currentScore){
makeFormScoreRegistration();
}
function makeFormScoreRegistration(){
var form = document.createElement("form");
form.setAttribute("id", "form");
form.setAttribute("action", "javascript:void(0);");
var label = document.createElement("label");
label.setAttribute("for", "userName");
var input = document.createElement("input");
input.setAttribute("id", "userName");
input.value = "User";
label.appendChild(input);
var submit = document.createElement("input");
submit.setAttribute("type", "submit");
submit.setAttribute("onclick", "getUserData();");
label.appendChild(submit);
form.appendChild(label);
var tableDiv = document.getElementById("tableContainer");
tableDiv.appendChild(form);
//document.body.appendChild(form);
}
function getUserData(){
SaveScoreIfItIsBestScore();
currentScore = 0;
showHighScore();
}
function SaveScoreIfItIsBestScore(){
var userInput = document.getElementById("userName").value;
var newScore = [];
var ar = [userInput, currentScore];
newScore.push(ar);
if(sessionStorage.length == 0){
saveCurrentScoreToSessionSt(newScore);
}
else {
var storage = sessionStorage.getItem("bestScores");
var arr = JSON.parse(storage);
if(arr.length < 5){
arr.push(ar);
}
else {
if(arr[arr.length-1][1] <= currentScore){
arr.pop();
arr.push(ar);
}
}
arr.sort(function(a, b) {return a[1] < b[1] ? 1 : -1;});
saveCurrentScoreToSessionSt(arr);
}
}
function saveCurrentScoreToSessionSt(arr){
sessionStorage.clear();
sessionStorage.setItem("bestScores", JSON.stringify(arr));
}
function showHighScore(){
var storage = sessionStorage.getItem("bestScores");
var arrayOfUsers = JSON.parse(storage);
var table = document.createElement("table");
table.setAttribute("id", "table");
var caption = table.createCaption().outerHTML = "<caption>High Score</capion>";
var thead = table.insertRow().outerHTML = "<tr><th>User</th><th>Score</th></tr>";
for(i=0; i < arrayOfUsers.length; i++){
var row = table.insertRow();
var userCell = row.insertCell().innerHTML = arrayOfUsers[i][0];
var scoreCell = row.insertCell().innerHTML = arrayOfUsers[i][1];
}
var tableDiv = document.getElementById("tableContainer");
tableDiv.appendChild(table);
deleteElement("form");
ctx.save();
ctx.font = "20px Arial";
ctx.fillText("Press enter to restart!", 20, 70);
ctx.restore();
window.addEventListener('keydown', gameOverRestart);
}
function deleteElement(id){
document.getElementById(id).outerHTML = "";
};
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Draw a monster in a canvas</title>
<link rel="stylesheet" type="text/css" href="style.css"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/howler/1.1.28/howler.min.js"></script>
</head>
<body>
<div class="container">
<div class="row">
<div id="controls" class="col-1-2">
<label for="nbBalls">Number of balls: </label>
<input type="number" min=1 max=30
value=10 id="nbBalls"
oninput="changeNbBalls(this.value);">
<p></p>
<label for="colorChooser">Player color: </label>
<input type="color" value='#FF0000' oninput="changePlayerColor(this.value);" id="colorChooser">
<p></p>
<label for="selectColorOfBallToEat">Color of ball to eat: </label>
<select onchange="changeColorToEat(this.value);" id="selectColorOfBallToEat">
<option value='red'>red</option>
<option value='blue'>blue</option>
<option value='green'>green</option>
</select>
<p></p>
<label for="ballSpeed">Change ball speed: </label>
- <input type="range" value='1' min=0.1 max=3 step=0.1 oninput="changeBallSpeed(this.value);" id="ballSpeed">
+
<p></p>
</div>
<div id="audioControls" class="col-1-2">
<label for="backgroundSong">Choose backgground song: </label>
<select id="audioControlsBackgroundSongs" onchange="changeBackgroundSong(this.value)">
<option value="xmas">Xmas</option>
<option value="humbug">Humbug</option>
<option value="concertino">Concertino</option>
</select>
<p></p>
<label for="songVolume">Song volume: </label>
<input id="songVolumeRange" type="range" min="0" max="10" value="" onchange="changeSongVolume(this.value)">
</div>
</div>
<div class="row">
<div id="tableContainer"></div>
<canvas id="myCanvas" width="400" height="400">
</canvas>
</div>
</div>
<script src="script.js"></script>
</body>
</html>
Game /EdX's JavaScript Introduction Course by W3Cx/
----------------------------------------------------
A [Pen](https://codepen.io/Onlyforbopi/pen/LgPypZ) by [Pan Doul](https://codepen.io/Onlyforbopi) on [CodePen](https://codepen.io).
[License](https://codepen.io/Onlyforbopi/pen/LgPypZ/license).
以上是关于markdown W3Cx的Game / EdX JavaScript入门课程/的主要内容,如果未能解决你的问题,请参考以下文章
html JS.Templates.Contact manager / EdX的W3Cx JavaScript入门课程/
html JS.JSON.Dynamic table / EdX的W3Cx的JavaScript入门课程/
html 来自https://courses.edx.org/courses/course-v1:W3Cx+HTML5.1x+3T2016/courseware/b246c15d3a1044ccb45
css 来自https://courses.edx.org/courses/course-v1:W3Cx+HTML5.1x+3T2016/courseware/b246c15d3a1044ccb456