|
@@ -11,6 +11,9 @@
|
|
|
<script type="text/javascript">
|
|
|
const FPS = 60;
|
|
|
const SCENE_SPEED = 3;
|
|
|
+ const SPEED_INCREASE = 0.2; //увеличение скорсоти на
|
|
|
+ const GEN_TIME = 5;
|
|
|
+ const LIFES = 1;
|
|
|
const PLANE_SIZE = 30; //plane height in pixels
|
|
|
const PLANE_ACCELERATION = 2/5; //TODO пока пиксели в секунду
|
|
|
const MISSLE_SPEED = 13; //TODO обдумать на размер сцены
|
|
@@ -18,14 +21,17 @@
|
|
|
const MISSLE_SIZEX = 5; //ширина снаряда
|
|
|
const SHOOT_COOLDOWN = 3/8; //в секундах
|
|
|
|
|
|
- const SHIPS_COUNT = 3; //начальное кол-во кораблей
|
|
|
+ const SHIPS_COUNT = 5; //начальное кол-во кораблей
|
|
|
const SHIP_SIZEY = 25; //высота корабля
|
|
|
const SHIP_SIZEX = 100; //ширина корабля
|
|
|
+ const CONTROL_START = 32;
|
|
|
const CONTROL_LEFT = 90; //90 - Z
|
|
|
const CONTROL_RIGHT = 88; //88 - X
|
|
|
const CONTROL_FIRE = 190; //190 - ,
|
|
|
|
|
|
const SHOW_BOUNDING = true;
|
|
|
+ const GOD = false;
|
|
|
+
|
|
|
|
|
|
/** @type {HTMLCanvasElement} */
|
|
|
var canv = document.getElementById("gameCanvas");
|
|
@@ -34,30 +40,17 @@
|
|
|
var score = 0;
|
|
|
|
|
|
var scene = { //хранит бэкраунд
|
|
|
- boundaries: []
|
|
|
- }
|
|
|
- addBoundaries();
|
|
|
-
|
|
|
- var plane = {
|
|
|
- x: canv.width / 2,
|
|
|
- y: canv.height / 2 + 100,
|
|
|
- r: PLANE_SIZE / 2,
|
|
|
- a: 90 / 180 * Math.PI,
|
|
|
- acceleration: {
|
|
|
- posx: false,
|
|
|
- negx: false,
|
|
|
- },
|
|
|
- speedx: 0,
|
|
|
- reload: false,
|
|
|
- reloadtime: 0,
|
|
|
- missles: [],
|
|
|
- collision: {
|
|
|
- x: 0,
|
|
|
- y: 0,
|
|
|
- w: PLANE_SIZE,
|
|
|
- h: PLANE_SIZE,
|
|
|
- },
|
|
|
+ lifes: LIFES,
|
|
|
+ speed: SCENE_SPEED,
|
|
|
+ gameOver: false,
|
|
|
+ genTimer: GEN_TIME * FPS,
|
|
|
+ blocks: []
|
|
|
+ //boundaries: []
|
|
|
}
|
|
|
+ addStartingBlock();
|
|
|
+
|
|
|
+ var plane;
|
|
|
+ newPlane();
|
|
|
|
|
|
var ships = [];
|
|
|
createShip();
|
|
@@ -69,23 +62,29 @@
|
|
|
//game loop
|
|
|
setInterval(update, 1000 / FPS);
|
|
|
|
|
|
- function addBoundaries(){
|
|
|
- scene.boundaries.push(addBounadry(0, 4 * 720, 1280 / 4));
|
|
|
- scene.boundaries.push(addBounadry(1280 - 1280 / 4, 4 * 720, 1280 / 4));
|
|
|
- scene.boundaries[0].collision.y += 720;
|
|
|
- scene.boundaries[1].collision.y += 720;
|
|
|
- //addBounadry();
|
|
|
- //addBounadry();
|
|
|
+ function addStartingBlock(){
|
|
|
+ var block = {
|
|
|
+ x: 0,
|
|
|
+ y: 0,
|
|
|
+ replaced: false,
|
|
|
+ boundaries: [],
|
|
|
+ }
|
|
|
+ block.x = 0;
|
|
|
+ block.y = -3 * 720;
|
|
|
+ block.boundaries.push(addBounadry(0, block.y, 1280 / 4, 4 * 720));
|
|
|
+ block.boundaries.push(addBounadry(1280 - 1280 / 4, block.y, 1280 / 4, 4 * 720));
|
|
|
+
|
|
|
+ scene.blocks.push(block);
|
|
|
}
|
|
|
|
|
|
- function addBounadry(bx,by,bw){
|
|
|
+ function addBounadry(bx,by,bw,bh){
|
|
|
var boundary = {
|
|
|
- replaced: false,
|
|
|
+ //replaced: false,
|
|
|
collision: {
|
|
|
x: bx,
|
|
|
- y: -by,
|
|
|
+ y: by,
|
|
|
w: bw,
|
|
|
- h: by,
|
|
|
+ h: bh,
|
|
|
}
|
|
|
}
|
|
|
return boundary;
|
|
@@ -93,8 +92,11 @@
|
|
|
|
|
|
function createShip() {
|
|
|
ships = [];
|
|
|
- for (var i = 0; i < SHIPS_COUNT; i++) {
|
|
|
- ships.push(newShip());
|
|
|
+ for (var i = 0; i < 3; i++) {
|
|
|
+ var ship = newShip();
|
|
|
+ if (ship != null) {
|
|
|
+ ships.push(ship);
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -102,13 +104,24 @@
|
|
|
function keyDown(/** @type {KeyboardEvent} */ ev) {
|
|
|
switch (ev.keyCode) {
|
|
|
case CONTROL_LEFT: //Move to the left
|
|
|
- plane.acceleration.negx = true;
|
|
|
+ if (!scene.gameOver){
|
|
|
+ plane.acceleration.negx = true;
|
|
|
+ }
|
|
|
break;
|
|
|
case CONTROL_RIGHT: //Move to the right
|
|
|
- plane.acceleration.posx = true;
|
|
|
+ if (!scene.gameOver){
|
|
|
+ plane.acceleration.posx = true;
|
|
|
+ }
|
|
|
break;
|
|
|
case CONTROL_FIRE: //Fire the missle
|
|
|
- shootMissle();
|
|
|
+ if (!scene.gameOver){
|
|
|
+ plane.shooting = true;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case CONTROL_START:
|
|
|
+ if (scene.gameOver){
|
|
|
+ newGame();
|
|
|
+ }
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
@@ -116,17 +129,61 @@
|
|
|
function keyUp(/** @type {KeyboardEvent} */ ev) {
|
|
|
switch (ev.keyCode) {
|
|
|
case CONTROL_LEFT: //Move to the left
|
|
|
- plane.acceleration.negx = false;
|
|
|
+ if (!scene.gameOver){
|
|
|
+ plane.acceleration.negx = false;
|
|
|
+ }
|
|
|
break;
|
|
|
case CONTROL_RIGHT: //Move to the right
|
|
|
- plane.acceleration.posx = false;
|
|
|
+ if (!scene.gameOver){
|
|
|
+ plane.acceleration.posx = false;
|
|
|
+ }
|
|
|
break;
|
|
|
case CONTROL_FIRE: //Fire the missle
|
|
|
+ if (!scene.gameOver){
|
|
|
+ plane.shooting = false;
|
|
|
+ }
|
|
|
//plane.reload = false;
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ function newGame() {
|
|
|
+ console.log("New Game!");
|
|
|
+ scene.blocks = [];
|
|
|
+ addStartingBlock();
|
|
|
+ newPlane();
|
|
|
+ createShip();
|
|
|
+ score = 0;
|
|
|
+ scene.gameOver = false;
|
|
|
+ scene.lifes = LIFES;
|
|
|
+ scene.speed = SCENE_SPEED;
|
|
|
+ scene.genTimer = GEN_TIME * FPS;
|
|
|
+ }
|
|
|
+
|
|
|
+ function newPlane() {
|
|
|
+ plane = {
|
|
|
+ x: canv.width / 2,
|
|
|
+ y: canv.height / 2 + 100,
|
|
|
+ r: PLANE_SIZE / 2,
|
|
|
+ a: 90 / 180 * Math.PI,
|
|
|
+ acceleration: {
|
|
|
+ posx: false,
|
|
|
+ negx: false,
|
|
|
+ },
|
|
|
+ speedx: 0,
|
|
|
+ shooting: false,
|
|
|
+ reload: false,
|
|
|
+ reloadtime: 0,
|
|
|
+ missles: [],
|
|
|
+ collision: {
|
|
|
+ x: 0,
|
|
|
+ y: 0,
|
|
|
+ w: PLANE_SIZE,
|
|
|
+ h: PLANE_SIZE,
|
|
|
+ },
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
function newShip(x) {
|
|
|
let direction
|
|
|
if (Math.floor(Math.random()*2) == 0) {
|
|
@@ -145,27 +202,44 @@
|
|
|
h: SHIP_SIZEY,
|
|
|
},
|
|
|
}
|
|
|
- var shipPosGeneration = true;
|
|
|
- while (shipPosGeneration == true) {
|
|
|
+ //console.log("shipgeneration");
|
|
|
+ var shipPosGeneration = 0;
|
|
|
+ while (shipPosGeneration != -1 && shipPosGeneration <= 10) {
|
|
|
ship.x = Math.floor(Math.random()*1280);
|
|
|
ship.collision.x = ship.x - SHIP_SIZEX / 2;
|
|
|
- shipPosGeneration = false;
|
|
|
- for (var i = 0; i < scene.boundaries.length; i++) {
|
|
|
- if (checkRectangularCollision(ship.collision, scene.boundaries[i].collision) ) {
|
|
|
- shipPosGeneration = true;
|
|
|
+ shipPosGenerationInit = shipPosGeneration;
|
|
|
+ for (var i = scene.blocks.length - 1; i >= 0 ; i--) {
|
|
|
+ for (var j = scene.blocks[i].boundaries.length - 1; j >= 0 ; j--) {
|
|
|
+ if (checkRectangularCollision(ship.collision, scene.blocks[i].boundaries[j].collision)) {
|
|
|
+ shipPosGeneration++;
|
|
|
+ i = -1;
|
|
|
+ j = -1;
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
- for (var i = 0; i < ships.length; i++)
|
|
|
- if (checkRectangularCollision(ship.collision, ships[i].collision) ) {
|
|
|
- shipPosGeneration = true;
|
|
|
+ if (shipPosGeneration == shipPosGenerationInit) {
|
|
|
+ for (var i = ships.length - 1; i >= 0; i--){
|
|
|
+ if (checkRectangularCollision(ship.collision, ships[i].collision) ) {
|
|
|
+ shipPosGeneration++;
|
|
|
+ i = -1;
|
|
|
+ }
|
|
|
}
|
|
|
+ }
|
|
|
+ //console.log(shipPosGeneration);
|
|
|
+ if (shipPosGeneration == shipPosGenerationInit) {
|
|
|
+ shipPosGeneration = -1;
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ if (shipPosGeneration >= 10) {
|
|
|
+ return null;
|
|
|
}
|
|
|
console.log(ship.x);
|
|
|
return ship;
|
|
|
}
|
|
|
|
|
|
function shootMissle() {
|
|
|
- if (!plane.reload) {
|
|
|
+ if (!plane.reload && plane.shooting) {
|
|
|
plane.missles.push({
|
|
|
x: plane.x + 4 / 3 * plane.r * Math.cos(plane.a),
|
|
|
y: plane.y - 4 / 3 * plane.r * Math.sin(plane.a),
|
|
@@ -183,12 +257,25 @@
|
|
|
|
|
|
}
|
|
|
|
|
|
+ function death() {
|
|
|
+ scene.lifes--;
|
|
|
+ ships = [];
|
|
|
+ if (scene.lifes == 0) {
|
|
|
+ console.log("Game Over!"); //в функции gameOver
|
|
|
+ console.log("Your Score:");
|
|
|
+ console.log(score);
|
|
|
+ scene.gameOver = true;
|
|
|
+ scene.speed = 0;
|
|
|
+
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
function checkRectangularCollision(a, b){ //проверка коллизии 2х прямоугольных объекттов
|
|
|
if (a.x < b.x + b.w &&
|
|
|
a.x + a.w > b.x &&
|
|
|
a.y < b.y + b.h &&
|
|
|
a.h + a.y > b.y) {
|
|
|
- console.log("collision detected");
|
|
|
+ //console.log("collision detected");
|
|
|
return true
|
|
|
}
|
|
|
else {
|
|
@@ -215,10 +302,10 @@
|
|
|
problem = true;
|
|
|
}
|
|
|
if (problem) {
|
|
|
- if (collsion.x < (c.x + c.w) && collsion.x > c.x) { //левостороняя коллизия
|
|
|
- return c.x + c.w + PLANE_SIZE/2;
|
|
|
+ if (collsion.x + PLANE_SIZE / 2 <= (c.x + c.w + PLANE_SIZE / 2) && collsion.x + PLANE_SIZE / 2 >= c.x + c.w / 2) { //левостороняя коллизия
|
|
|
+ return c.x + c.w + PLANE_SIZE / 2;
|
|
|
}
|
|
|
- if (collsion.x + collsion.w > c.x && collsion.x + collsion.w < c.x + c.w) { //правостороняя коллизия
|
|
|
+ if (collsion.x + PLANE_SIZE / 2 > c.x - PLANE_SIZE / 2 && collsion.x + PLANE_SIZE / 2 < c.x + c.w / 2) { //правостороняя коллизия
|
|
|
return c.x - plane.r;
|
|
|
}
|
|
|
|
|
@@ -241,9 +328,11 @@
|
|
|
ctx.fillRect(0,0, canv.width, canv.height)
|
|
|
|
|
|
//отрисовка бэкграунда
|
|
|
- for (var i = 0; i < scene.boundaries.length; i++) {
|
|
|
- if (SHOW_BOUNDING) {
|
|
|
- drawCollision(scene.boundaries[i].collision,"blue");
|
|
|
+ for (var i = 0; i < scene.blocks.length; i++) {
|
|
|
+ for (var j = 0; j < scene.blocks[i].boundaries.length; j++) {
|
|
|
+ if (SHOW_BOUNDING) {
|
|
|
+ drawCollision(scene.blocks[i].boundaries[j].collision,"green");
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -252,7 +341,10 @@
|
|
|
//коллизия кораблей с самолётом
|
|
|
for (var i = 0; i < ships.length; i++){
|
|
|
if (checkRectangularCollision(ships[i].collision, plane.collision)) {
|
|
|
- console.log("Plane collading with ship no. " + i )
|
|
|
+ console.log("Plane collading with ship no. " + i);
|
|
|
+ if (!GOD) {
|
|
|
+ death();
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
//коллизия снаряда с кораблями
|
|
@@ -264,7 +356,10 @@
|
|
|
ships.splice(i,1);
|
|
|
score += 30;
|
|
|
console.log("New score: " + score);
|
|
|
- ships.push(newShip());
|
|
|
+ var ship = newShip();
|
|
|
+ if (ship != null) {
|
|
|
+ ships.push(ship);
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
}
|
|
@@ -272,33 +367,65 @@
|
|
|
|
|
|
//move scene
|
|
|
//движение бэкграунда
|
|
|
- for (var i = scene.boundaries.length - 1; i >= 0; i--) {
|
|
|
- //scene.boundaries[i]
|
|
|
-
|
|
|
- if (scene.boundaries[i].collision.y > 720 ) { //удаление ушедших границ
|
|
|
- scene.boundaries.splice(i,1);
|
|
|
+ for (var i = scene.blocks.length - 1; i >= 0; i--) {
|
|
|
+ if (scene.blocks[i].y > 720 ) { //удаление ушедшего блока
|
|
|
+ scene.blocks.splice(i,1);
|
|
|
continue;
|
|
|
}
|
|
|
- if (scene.boundaries[i].collision.y > 0 && !scene.boundaries[i].replaced) {
|
|
|
- scene.boundaries.push(addBounadry(scene.boundaries[i].collision.x, 4 * 720, scene.boundaries[i].collision.w));
|
|
|
- scene.boundaries[scene.boundaries.length - 1].collision.y =
|
|
|
- scene.boundaries[i].collision.y - scene.boundaries[scene.boundaries.length - 1].collision.h + SCENE_SPEED;
|
|
|
- scene.boundaries[i].replaced = true;
|
|
|
+ if (scene.blocks[i].y > 0 && !scene.blocks[i].replaced) { //подстановка нового блока
|
|
|
+
|
|
|
+ var block = {
|
|
|
+ x: 0,
|
|
|
+ y: scene.blocks[i].y - (4 * 720) + scene.speed,
|
|
|
+ replaced: false,
|
|
|
+ boundaries: [],
|
|
|
+ }
|
|
|
+ block.boundaries.push(addBounadry(0, block.y, 1280 / 4, 4 * 720));
|
|
|
+ block.boundaries.push(addBounadry(1280 - 1280 / 4, block.y, 1280 / 4, 4 * 720));
|
|
|
+ block.boundaries.push(addBounadry(1280 / 2 - 1280 / 8, block.y + 720, 1280 / 4, 2 * 720));
|
|
|
+ block.boundaries.push(addBounadry(1280 / 2 - 1280 / 8 + PLANE_SIZE / 2, block.y + 720 - PLANE_SIZE / 2, 1280 / 4 - PLANE_SIZE, 2 * 720 + PLANE_SIZE));
|
|
|
+ block.boundaries.push(addBounadry(1280 / 2 - 1280 / 8 + PLANE_SIZE, block.y + 720 - PLANE_SIZE, 1280 / 4 - 2 * PLANE_SIZE, 2 * 720 + 2 * PLANE_SIZE));
|
|
|
+ scene.blocks.push(block);
|
|
|
+
|
|
|
+ scene.blocks[i].replaced = true;
|
|
|
}
|
|
|
- scene.boundaries[i].collision.y += SCENE_SPEED; //TODO двигать нет только коллизию
|
|
|
- //console.log(scene.boundaries[i].collision.y);
|
|
|
+
|
|
|
+ //движение блока, его баундари(TODO) и коллизий внутри
|
|
|
+ scene.blocks[i].y += scene.speed;
|
|
|
+
|
|
|
+ for (var j = scene.blocks[i].boundaries.length - 1; j >= 0; j--) {
|
|
|
+ scene.blocks[i].boundaries[j].collision.y += scene.speed; //TODO двигать не только коллизию
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
|
|
|
+ scene.genTimer--;
|
|
|
+ //console.log(scene.genTimer);
|
|
|
+ if (scene.genTimer == 0 && !scene.gameOver) {
|
|
|
+ if (ships.length < SHIPS_COUNT) {
|
|
|
+ var ship = newShip();
|
|
|
+ if (ship != null) {
|
|
|
+ ships.push(ship);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ scene.speed += SPEED_INCREASE;
|
|
|
+ console.log("New speed:");
|
|
|
+ console.log(scene.speed);
|
|
|
+ scene.genTimer = 5 * FPS;
|
|
|
+ }
|
|
|
+
|
|
|
//двигаем объекты
|
|
|
//двигаем корабли
|
|
|
for (var i = ships.length - 1; i >= 0 ; i--){
|
|
|
if (ships[i].y > 720 + SHIP_SIZEY / 2) { //удаление снарядов за экраном
|
|
|
ships.splice(i,1);
|
|
|
- ships.push(newShip());
|
|
|
+ var ship = newShip();
|
|
|
+ if (ship != null) {
|
|
|
+ ships.push(ship);
|
|
|
+ }
|
|
|
continue;
|
|
|
}
|
|
|
- ships[i].y += SCENE_SPEED;
|
|
|
+ ships[i].y += scene.speed;
|
|
|
ships[i].collision.x = ships[i].x - SHIP_SIZEX / 2;
|
|
|
ships[i].collision.y = ships[i].y - SHIP_SIZEY / 2;
|
|
|
//console.log(ships[i].collision.w);
|
|
@@ -431,6 +558,8 @@
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ shootMissle();
|
|
|
+
|
|
|
//update acceleration
|
|
|
if (plane.acceleration.posx ^ plane.acceleration.negx){
|
|
|
//console.log("acceleration calc")
|
|
@@ -449,23 +578,25 @@
|
|
|
|
|
|
//move the plane
|
|
|
//TODO размер сцены
|
|
|
- rightBorder = 1280;
|
|
|
- leftBorder = 0;
|
|
|
- for (var i = 0; i < scene.boundaries.length; i++) {
|
|
|
- var newPlaneX = checkPlaneSceneCollision(plane.x - plane.speedx, plane.y,scene.boundaries[i].collision)
|
|
|
- if (newPlaneX != 0){
|
|
|
- plane.speedx = 0;
|
|
|
- plane.x = newPlaneX;
|
|
|
- //plane.acceleration.negx = false;
|
|
|
- //plane.acceleration.posx = false;
|
|
|
- console.log("collsion with boundary no." + i)
|
|
|
+ if (!scene.gameOver) {
|
|
|
+ for (var i = 0; i < scene.blocks.length; i++) {
|
|
|
+ for (var j = 0; j < scene.blocks[i].boundaries.length; j++) {
|
|
|
+ var newPlaneX = checkPlaneSceneCollision(plane.x - plane.speedx, plane.y,scene.blocks[i].boundaries[j].collision)
|
|
|
+ if (newPlaneX != 0){
|
|
|
+ plane.speedx = 0;
|
|
|
+ plane.x = newPlaneX;
|
|
|
+ console.log("collsion with boundary no." + j + " in block no. " + i);
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
+ plane.x -= plane.speedx;
|
|
|
}
|
|
|
- plane.x -= plane.speedx;
|
|
|
|
|
|
|
|
|
|
|
|
- /*
|
|
|
+ /*
|
|
|
+ rightBorder = 1280;
|
|
|
+ leftBorder = 0;
|
|
|
if ((plane.x - plane.speedx) <= (rightBorder - plane.r) && (plane.x - plane.speedx) >= (0 + plane.r))
|
|
|
{ plane.x -= plane.speedx;
|
|
|
} else {
|