1. Resuma os principais pontos e problemas encontrados
1. Herança em JavaScript, é melhor para a classe pai fornecer apenas compartilhamento de métodos e os atributos são gravados em suas respectivas subclasses para evitar a confusão dos construtores da classe pai e da subclasse.
2. O protótipo simula o código herdado e deve ser gravado antes de todas as definições de método.
A cópia do código é a seguinte:
Hero.prototype = novo tanque (0, 0, 0);
Hero.prototype.Constructor = Hero;
Hero.prototype.addlife = function () {
this.lifetimes ++;
Document.QuerySelector ("#Life"). INNERHTML = HERO.LIFETIMENTES;
}
3. Ao desenhar um gráfico, exceto o retângulo, você deve adicionar ctx.beginpath ();
4. A função concat pode mesclar matrizes ou devolver um elemento a uma nova matriz
5. A imagem será carregada após o atributo SRC ser atribuído, mas se a imagem não for carregada, causará falhas; portanto, use o evento OnLoad para lidar com ela.
6. Expanda a função da matriz e exclua o elemento especificado
A cópia do código é a seguinte:
// se estende para excluir o elemento especificado
Array.prototype.DeleteElement = function (obj) {
if (obj) {
for (var i = 0; i <this.length; i ++) {
if (este [i] === obj) {
this.splice (i, 1);
}
}
}
}
7. Configurações do timer, o primeiro parâmetro do método setInterval ("Fun", 1000) pode ser uma string, como "Hero.Say ()", semelhante a Eval, executará essa sequência de código, para que possa dar o Funcionar o parâmetro superior e também especifica o contexto em execução dessa função. Mas se o passe é um identificador para uma função, não pode levar parâmetros e o contexto não pode ser especificado.
A cópia do código é a seguinte:
// Timer, exercite -se sozinho
this.timer = setInterval ((function (context) {
Return function () {
Bullet.prototype.move.call (contexto)
}
}) (this), 30);
Eu salvei o ambiente de execução atual e liguei para o método de chamada para executar manualmente.
8. O design funcional do método, além das funções, deve incluir a detecção condicional dessa função, como o Move, que deve incluir em que circunstâncias pode ser movido e onde quer que você não possa se mover. Esta detecção não deve ser colocada externamente.
9. Ao escrever código, você não deve pensar em design ou otimização. Seja claro ao pensar, não fique confuso e concentre -se em uma coisa.
10. JavaScript não tem função de sono, você pode criar uma variável como um buffer para alcançar o objetivo da execução do intervalo
2. Implementação de código
1. Este programa é dividido em bomb.js, bullet.js, draw.js, tank.js, index.html, img, música,
2. Efeito final
3. Código
1.Index.html
A cópia do código é a seguinte:
<! Doctype html>
<html>
<head>
<Title> </title>
<meta charset = "utf-8">
<style type = "text/css">
corpo {
Fonte: 14px "Sans-Serif"
}
#Map {
Background-Color: #000000;
}
.mostrar {
Float: Esquerda
}
#guia {
flutuar: esquerda;
Largura: 200px;
Altura: 390px;
margem-esquerda: 5px;
Antecedentes: #CCCCCC;
preenchimento: 5px;
}
</style>
<script type = "text/javascript" src = "tank.js"> </script>
<script type = "text/javascript" src = "bullet.js"> </script>
<script type = "text/javascript" src = "bomb.js"> </sCript>
<script type = "text/javascript" src = "draw.js"> </sCript>
<script type = "text/javascript">
window.onload = function () {
// informações de tela
largura = document.getElementById ('mapa'). largura;
altura = document.getElementById ('mapa'). Hight;
ctx = document.getElementById ('map'). getContext ('2d');
// página inicial
var starImg = new Image ();
starimg.src = "img/star.jpg";
starimg.onload = function () {
ctx.drawimage (starimg, 0, 0, largura, altura);
}
// Monitoramento do teclado e retorne para iniciar o jogo
document.body.onkeydown = function () {
var keycode = event.keycode;
Switch (KeyCode) {
Caso 13:
// Parâmetros de inicialização
init ()
// Atualize a página
setInterval (desenho, 30);
document.body.onkeydown = gameControl;
quebrar;
}
}
}
function init () {
// jogadores e computadores
herói = novo herói (100, 300, 0);
inimys = [];
for (var i = 0; i <3; i ++) {
Enemys.push (novo inimigo (100 + i * 50, 0, 2));
}
// Merge Array
alltank = inimys.concat (herói);
//bomba
Bombas = [];
im = new image ();
im2 = new imagem ();
im3 = new image ();
im.src = "img/bomb_3.gif";
im2.src = "img/bomb_2.gif";
im3.src = "img/bomb_1.gif";
}
função gameControl () {
var keycode = event.keycode;
Switch (KeyCode) {
Caso 65:
Hero.moveleft ();
quebrar; // esquerda
Caso 83:
Hero.MoveDown ();
quebrar; // próximo
Caso 87:
Hero.MoveUp ();
quebrar; // on
Caso 68:
Hero.Moveright ();
quebrar; // certo
Caso 74:
hero.shot ();
quebrar;
Caso 49:
Hero.addlife ()
quebrar;
}
}
// se estende para excluir o elemento especificado
Array.prototype.DeleteElement = function (obj) {
if (obj) {
for (var i = 0; i <this.length; i ++) {
if (este [i] === obj) {
this.splice (i, 1);
}
}
}
}
</script>
</head>
<Body>
<div>
<canvas id = "map">
</canvas>
<Audio ID = "Music" AutoPlay = "AutoPlay">
<fonte src = "music/111.wav">
</udio>
</div>
<div id = "guia">
<p> Pressione Enter para iniciar o jogo </p>
<p> Pressione 1 tecla para aumentar a vida, o padrão é 1 </p>
<p> Contagem de vida restante: <gravador id = "Life"> 1 </belt> </p>
<div id = "dados">
</div>
</div>
</body>
</html>
2.draw.js
A cópia do código é a seguinte:
/**
* Criado por Alane em 14-3-18.
*/
função draw () {
// Detecção de vida e morte de balas e tanques
checkDead ();
// Limpe a tela
ctx.clearrect (0,0,500.400);
// Desenhe o jogador
if (! hero.isdead) {
drawtank (herói);
}outro{
hero.cutlife ();
}
// desenha tanques inimigos
for (var i = 0; i <inimys.length; i ++) {
drawtank (inimigo [i]);
}
// desenha balas inimigas
for (var j = 0; j <inimys.length; j ++) {
var temp = inimys [j] .BulletsList;
for (var i = 0; i <temp.length; i ++) {
drawbullet (temp [i]);
}
}
// desenha a bala do jogador
var temp = Hero.BulletsList;
for (var i = 0; i <temp.length; i ++) {
drawbullet (temp [i]);
}
// Desenhe bomba
for (var i = 0; i <bombs.length; i ++) {
drawbown (bombas [i]);
}
}
função drawTank (tank) {
var x = tank.x;
var y = tank.y;
ctx.fillstyle = tank.color;
if (tank.direct == 0 || tank.direct == 2) {
ctx.fillrect (x, y, 5,30);
ctx.FillRect (x+15, y, 5,30);
ctx.fillRect (x+6, y+8, 8,15);
ctx.strokestyle = tank.color;
ctx.LineWidth = '1.5';
if (tank.direct == 0) {
ctx.BeginPath ();
ctx.moveto (x+10, y-2);
ctx.lineto (x+10, y+8);
ctx.closePath ();
}outro{
ctx.BeginPath ();
ctx.moveto (x+10, y+24);
ctx.lineto (x+10, y+32);
ctx.closePath ();
}
ctx.stroke ();
}outro{
ctx.fillrect (x, y, 30,5);
ctx.fillRect (x, y+15, 30,5);
ctx.fillRect (x+8, y+6, 15,8);
ctx.strokestyle = '#ff0000';
ctx.LineWidth = '1.5';
if (tank.direct == 3) {
ctx.BeginPath ();
ctx.moveto (x-2, y+10);
ctx.lineto (x+8, y+10);
ctx.closePath ();
}outro{
ctx.BeginPath ();
ctx.moveto (x+24, y+10);
ctx.lineto (x+32, y+10);
ctx.closePath ();
}
ctx.stroke ();
}
}
função drawbullet (bala) {
ctx.fillstyle = bullet.color;
ctx.BeginPath ();
ctx.arc (Bullet.x, Bullet.y, 2.360, verdadeiro);
ctx.closePath ();
ctx.fill ();
}
função drawbown (obj) {
if (obj.life> 8) {
ctx.Drawimage (IM, Obj.x, obj.y, 50,50);
} else if (obj.life> 4) {
ctx.drawimage (im2, obj.x, obj.y, 50,50);
}outro{
ctx.drawimage (im3, obj.x, obj.y, 50,50);
}
obj.lifedown ();
if (obj.life <= 0) {
Bombs.DeleteElement (OBJ);
}
}
função checkDead () {
// Detecção da vida e morte da bala inimiga
for (var j = 0; j <inimys.length; j ++) {
var temp = inimys [j] .BulletsList;
for (var i = 0; i <temp.length; i ++) {
var o = temp [i];
if (o.isdead) {
temp.deleteElement (O);
}
}
}
// Detecção da vida e morte de bala de jogadores
var temp = Hero.BulletsList;
for (var i = 0; i <temp.length; i ++) {
var o = temp [i];
if (o.isdead) {
temp.deleteElement (O);
}
}
// Detecção da vida e morte do tanque inimigo
for (var i = 0; i <inimys.length; i ++) {
var o = inimigo [i];
if (o.isdead) {
Enemys.DeleteElement (O);
}
}
}
BOMB.JS
A cópia do código é a seguinte:
/**
* Criado por Alane em 14-3-18.
*/
bomba de função (x, y) {
this.life = 12;
this.x = x;
this.y = y;
}
Bomb.prototype.lifedown = function () {
this.life--;
}
Tank.js
A cópia do código é a seguinte:
/**
* Criado por Alane em 14-3-7.
*/
/**
* direto 0 em
* 1 certo
* 2
* 3 esquerda
* @param x
* @param y
* @param direto
* @Constructor
*/
// ************************************************** **************************************************** **************************************************** **************************************************** **************************************************** **************************************************** **************************************************** ***************************************************** ****************************/
// Classe pai do tanque
tanque de função (x, y, direto) {
this.speed = 2;
}
Tank.prototype.moveup = function () {
// Detecção de fronteira
if (this.y <0) {
// Mude a direção
this.changedirect ();
retornar;
}
this.y -= this.speed;
this.direct = 0;
}
Tank.prototype.movedown = function () {
if (this.y> altura - 30) {
this.changedirect ();
retornar;
}
this.y += this.speed;
this.direct = 2;
}
Tank.prototype.moveleft = function () {
if (this.x <0) {
this.changedirect ();
retornar;
}
this.x -= this.speed;
this.direct = 3;
}
Tank.prototype.Moveright = function () {
if (this.x> width - 30) {
this.changedirect ();
retornar;
}
this.x += this.speed;
this.direct = 1;
}
// Mude a direção
Tank.prototype.changedirect = function () {
while (true) {
var temp = Math.Round (Math.random () * 3);
if (this.direct! = temp) {
this.direct = temp;
quebrar;
}
}
//alert("x="+this.x+ "y ="+this.y+"diretor ="+this.direct)
}
// balas de tiro
Tank.prototype.shot = function () {
if (this.isdead) {
retornar;
}
if (this.bulletslist.length <this.maxbulletsize) {
// Crie uma nova bala
var bala = nulo;
switch (this.direct) {
Caso 0:
bala = nova bala (this.x + 10, this.y - 2, 0, this.color);
quebrar;
Caso 1:
bala = nova bala (this.x + 32, this.y + 10, 1, this.color);
quebrar;
Caso 2:
bala = nova bala (this.x + 10, this.y + 32, 2, this.color);
quebrar;
Caso 3:
bala = nova bala (this.x - 2, this.y + 10, 3, this.color);
quebrar;
}
// coloque na revista
this.bulletslist.push (bala);
}
}
// ************************************************** **************************************************** **************************************************** **************************************************** **************************************************** **************************************************** **************************************************** ***************************************************** ****************************/
//Jogador
função herói (x, y, direto) {
this.lifetimes = 5;
this.isdead = false;
this.color = '#ff0000';
this.x = x;
this.y = y;
this.direct = direto;
this.bulletsList = [];
this.maxbulletsize = 10;
this.Newlife = null;
}
Hero.prototype = novo tanque (0, 0, 0);
Hero.prototype.Constructor = Hero;
Hero.prototype.addlife = function () {
this.lifetimes ++;
Document.QuerySelector ("#Life"). INNERHTML = HERO.LIFETIMENTES;
}
Hero.prototype.cutlife = function () {
if (this.lifetimes> = 1 &&! this.newlife) {
this.lifetimes--;
this.NewLife = setTimeout ("hero.newlife ()", 2000);
}
}
Hero.prototype.newlife = function () {
this.isdead = false;
ClearTimeout (Hero.newlife);
hero.newlife = null;
Document.QuerySelector ("#Life"). INNERHTML = HERO.LIFETIMENTES;
}
// ************************************************** **************************************************** **************************************************** **************************************************** **************************************************** **************************************************** **************************************************** ***************************************************** ****************************/
// Tanque inimigo
função inimigo (x, y, direto) {
this.isdead = false;
this.color = 'azul';
this.x = x;
this.y = y;
this.direct = direto;
this.bulletsList = [];
this.maxbulletsize = 1;
// Timer, movimento automático
this.timer1 = setInterval ((function (context) {
Return function () {
//mover
Inimy.prototype.move.call (contexto);
}
}) (this), 30);
// temporizador, tiro
this.timer2 = setInterval ((function (context) {
Return function () {
//tiroteio
Tank.prototype.shot.call (contexto);
}
}) (this), 2000);
// Timer, altere a direção
this.timer3 = setInterval ((function (context) {
Return function () {
//tiroteio
Tank.prototype.changedirect.call (contexto);
}
}) (this), 3000);
}
Inimigo.prototype = novo tanque (0, 0, 0);
Inimigo.prototype.constructor = inimigo;
Inimy.prototype.move = function () {
switch (this.direct) {
Caso 0:
this.moveup ();
quebrar;
Caso 1:
this.Moveright ();
quebrar;
Caso 2:
this.MoveDown ();
quebrar;
Caso 3:
this.moveleft ();
quebrar;
}
}
Bullet.js
A cópia do código é a seguinte:
/**
* Criado por Alane em 14-3-11.
*/
Função Bullet (x, y, direto, cor) {
this.isdead = false;
this.x = x;
this.y = y;
this.direct = direto;
this.speed = 4;
this.color = cor;
// Timer, exercite -se sozinho
this.timer = setInterval ((function (context) {
Return function () {
Bullet.prototype.move.call (contexto)
}
}) (this), 30);
}
Bullet.prototype.move = function () {
switch (this.direct) {
Caso 0:
this.y -= this.speed;
quebrar;
Caso 1:
this.x += this.speed;
quebrar;
Caso 2:
this.y += this.speed;
quebrar;
Caso 3:
this.x -= this.speed;
quebrar;
}
// Detecção de fronteira
if (this.y <0 || this.x> width || this.y> altura || this.x <0) {
ClearInterval (this.timer);
this.isdead = true;
}
// Detecção de colisão detecta tanques inimigos
for (var i = 0; i <alltank.length; i ++) {
var temp = alltank [i];
if (temp.isdead) {
continuar;
}
Switch (temp.direct) {
Caso 0:
Caso 2: if (this.x> temp.x && this.x <temp.x+20 && this.y> temp.y && this.y <temp.y+30) {
if (this.color == temp.color) {
quebrar;
}
Bombs.push (nova bomba (temp.x-10, temp.y-10));
ClearInterval (this.timer);
this.isdead = true;
temp.isdead = true;
}quebrar
Caso 1:
Caso 3: if (this.x> temp.x && this.x <temp.x+30 && this.y> temp.y && this.y <temp.y+20) {
if (this.color == temp.color) {
quebrar;
}
Bombs.push (nova bomba (temp.x-10, temp.y-10));
ClearInterval (this.timer);
this.isdead = true;
temp.isdead = true;
}quebrar;
}
}
}
Download do código -fonte