123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507 |
- <!DOCTYPE html>
- <html>
- <head>
- <meta charset="UTF-8">
- <title>Raid on river</title>
- <style></style>
- </head>
- <body>
- <canvas id="gameCanvas" width="1280" height="720"></canvas>
- <script type="text/javascript">
- const FPS = 60;
- const SCENE_SPEED = 3;
- const PLANE_SIZE = 30; //plane height in pixels
- const PLANE_ACCELERATION = 2/5; //TODO пока пиксели в секунду
- const MISSLE_SPEED = 13; //TODO обдумать на размер сцены
- const MISSLE_SIZEY = 20/3*2; //длина снаряда
- const MISSLE_SIZEX = 5; //ширина снаряда
- const SHOOT_COOLDOWN = 3/8; //в секундах
-
- const SHIPS_COUNT = 3; //начальное кол-во кораблей
- const SHIP_SIZEY = 25; //высота корабля
- const SHIP_SIZEX = 100; //ширина корабля
- const CONTROL_LEFT = 90; //90 - Z
- const CONTROL_RIGHT = 88; //88 - X
- const CONTROL_FIRE = 190; //190 - ,
- const SHOW_BOUNDING = true;
- /** @type {HTMLCanvasElement} */
- var canv = document.getElementById("gameCanvas");
- var ctx = canv.getContext("2d");
- 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,
- },
- }
- var ships = [];
- createShip();
- //set up event handler
- document.addEventListener("keydown", keyDown);
- document.addEventListener("keyup", keyUp);
- //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 addBounadry(bx,by,bw){
- var boundary = {
- replaced: false,
- collision: {
- x: bx,
- y: -by,
- w: bw,
- h: by,
- }
- }
- return boundary;
- }
- function createShip() {
- ships = [];
- for (var i = 0; i < SHIPS_COUNT; i++) {
- ships.push(newShip());
- }
- }
- //key events
- function keyDown(/** @type {KeyboardEvent} */ ev) {
- switch (ev.keyCode) {
- case CONTROL_LEFT: //Move to the left
- plane.acceleration.negx = true;
- break;
- case CONTROL_RIGHT: //Move to the right
- plane.acceleration.posx = true;
- break;
- case CONTROL_FIRE: //Fire the missle
- shootMissle();
- break;
- }
- }
- function keyUp(/** @type {KeyboardEvent} */ ev) {
- switch (ev.keyCode) {
- case CONTROL_LEFT: //Move to the left
- plane.acceleration.negx = false;
- break;
- case CONTROL_RIGHT: //Move to the right
- plane.acceleration.posx = false;
- break;
- case CONTROL_FIRE: //Fire the missle
- //plane.reload = false;
- break;
- }
- }
- function newShip(x) {
- let direction
- if (Math.floor(Math.random()*2) == 0) {
- direction = -1;
- } else {
- direction = 1;
- }
- var ship = {
- x: 0,
- y: 0 - SHIP_SIZEY,
- a: direction,
- collision: {
- x: 0,
- y: 0,
- w: SHIP_SIZEX,
- h: SHIP_SIZEY,
- },
- }
- var shipPosGeneration = true;
- while (shipPosGeneration == true) {
- 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;
- }
- }
- for (var i = 0; i < ships.length; i++)
- if (checkRectangularCollision(ship.collision, ships[i].collision) ) {
- shipPosGeneration = true;
- }
- }
- console.log(ship.x);
- return ship;
- }
- function shootMissle() {
- if (!plane.reload) {
- 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),
- collision: {
- x: plane.x + 4 / 3 * plane.r * Math.cos(plane.a) - MISSLE_SIZEX / 2,
- y: plane.y - 4 / 3 * plane.r * Math.sin(plane.a),
- w: MISSLE_SIZEX,
- h: MISSLE_SIZEY,
- },
- })
- console.log("*shoot*");
- plane.reloadtime = SHOOT_COOLDOWN * FPS;
- plane.reload = true;
- }
- }
- 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");
- return true
- }
- else {
- //console.log("no collision");
- return false;
- }
- }
- function checkPlaneSceneCollision(x,y,c) { //проверка коллизии самолёта с сценой
- var collsion = {
- x: x + 4 / 3 * plane.r * Math.cos(plane.a) - PLANE_SIZE / 2,
- y: y - 4 / 3 * plane.r * Math.sin(plane.a),
- w: PLANE_SIZE,
- h: PLANE_SIZE,
- }
- //plane.collision.x =
- //plane.collision.y = plane.y - 4 / 3 * plane.r * Math.sin(plane.a)
- var problem = false;
- if (collsion.x < c.x + c.w &&
- collsion.x + collsion.w > c.x &&
- collsion.y < c.y + c.h &&
- collsion.h + collsion.y > c.y) {
- 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 + collsion.w > c.x && collsion.x + collsion.w < c.x + c.w) { //правостороняя коллизия
- return c.x - plane.r;
- }
- }
- else {
- return 0;
- }
- return 1280/2;
- }
- function drawCollision(a, color) { //Рисует коллизию объекта
- ctx.strokeStyle = color;
- ctx.strokeRect(a.x, a.y, a.w, a.h);
- }
- function update() {
- //draw scene
- ctx.fillStyle = "black";
- 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 < ships.length; i++){
- if (checkRectangularCollision(ships[i].collision, plane.collision)) {
- console.log("Plane collading with ship no. " + i )
- }
- }
- //коллизия снаряда с кораблями
- for (var i = ships.length - 1; i >= 0; i--){
- for (var j = plane.missles.length - 1; j >= 0; j--) {
- if (checkRectangularCollision(ships[i].collision, plane.missles[j].collision)) {
- console.log("Missle no. " + j + " collading with ship no. " + i )
- plane.missles.splice(j,1);
- ships.splice(i,1);
- score += 30;
- console.log("New score: " + score);
- ships.push(newShip());
- }
- }
- }
- //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);
- 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;
- }
- scene.boundaries[i].collision.y += SCENE_SPEED; //TODO двигать нет только коллизию
- //console.log(scene.boundaries[i].collision.y);
- }
- //двигаем объекты
- //двигаем корабли
- for (var i = ships.length - 1; i >= 0 ; i--){
- if (ships[i].y > 720 + SHIP_SIZEY / 2) { //удаление снарядов за экраном
- ships.splice(i,1);
- ships.push(newShip());
- continue;
- }
- 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);
- }
- //рисуем корабли
- for (var i = 0; i < ships.length ; i++){
- ctx.beginPath();
- ctx.moveTo( //корабля
- ships[i].x + ships[i].a * (SHIP_SIZEX / 6),
- ships[i].y - SHIP_SIZEY / 2
- )
- ctx.lineTo(
- ships[i].x - ships[i].a * (SHIP_SIZEX / 20 ) + ships[i].a * (SHIP_SIZEX / 6),
- ships[i].y - SHIP_SIZEY / 2
- )
- ctx.lineTo(
- ships[i].x - ships[i].a * (SHIP_SIZEX / 13) + ships[i].a * (SHIP_SIZEX / 6),
- ships[i].y - SHIP_SIZEY / 4
- )
- ctx.lineTo(
- ships[i].x - ships[i].a * (SHIP_SIZEX / 5) + ships[i].a * (SHIP_SIZEX / 6),
- ships[i].y - SHIP_SIZEY / 4
- )
- ctx.lineTo(
- ships[i].x - ships[i].a * (SHIP_SIZEX / 3) + ships[i].a * (SHIP_SIZEX / 6),
- ships[i].y + SHIP_SIZEY / 6
- )
- ctx.lineTo(
- ships[i].x - ships[i].a * SHIP_SIZEX / 2,
- ships[i].y + SHIP_SIZEY / 6
- )
- ctx.lineTo(
- ships[i].x - ships[i].a * SHIP_SIZEX * 2 / 7,
- ships[i].y + SHIP_SIZEY / 2
- )
- ctx.lineTo(
- ships[i].x + ships[i].a * SHIP_SIZEX / 3,
- ships[i].y + SHIP_SIZEY / 2
- )
- ctx.lineTo(
- ships[i].x + ships[i].a * SHIP_SIZEX / 2 ,
- ships[i].y + SHIP_SIZEY / 6
- )
- ctx.lineTo(
- ships[i].x + ships[i].a * SHIP_SIZEX / 2 - ships[i].a * SHIP_SIZEX / 10 ,
- ships[i].y + SHIP_SIZEY / 6
- )
- ctx.lineTo(
- ships[i].x + ships[i].a * (SHIP_SIZEX / 6),
- ships[i].y - SHIP_SIZEY / 4
- )
- ctx.closePath();
- ctx.fillStyle = "red";
- ctx.fill();
- if (SHOW_BOUNDING) {
- ctx.strokeStyle = "lime";
- ctx.strokeRect(
- ships[i].x - SHIP_SIZEX / 2,
- ships[i].y - SHIP_SIZEY / 2,
- SHIP_SIZEX,
- SHIP_SIZEY
- )
- }
- }
- //draw plane
- //ctx.lineWidth = PLANE_SIZE / 20;
- ctx.beginPath();
- ctx.moveTo( //nose of the plane
- plane.x + 4 / 3 * plane.r * Math.cos(plane.a),
- plane.y - 4 / 3 * plane.r * Math.sin(plane.a)
- );
- ctx.lineTo( //rear left of the plane
- plane.x - plane.r * (2 / 3 * Math.cos(plane.a) + Math.sin(plane.a)),
- plane.y + plane.r * (2 / 3 * Math.sin(plane.a) - Math.cos(plane.a))
- );
- ctx.lineTo( //rear right of the plane
- plane.x - plane.r * (2 / 3 * Math.cos(plane.a) - Math.sin(plane.a)),
- plane.y + plane.r * (2 / 3 * Math.sin(plane.a) + Math.cos(plane.a))
- );
- ctx.closePath();
- ctx.fillStyle = "yellow";
- ctx.fill();
- //ctx.strokeStyle = "yellow";
- //ctx.stroke();
- if (SHOW_BOUNDING) {
- //console.log(plane.collision.x);
- drawCollision(plane.collision,"blue");
- }
- //Рисуем снаряды
- for (var i = 0; i < plane.missles.length; i++) {
- ctx.beginPath();
- ctx.moveTo( //верхушка снаряда
- plane.missles[i].x,
- plane.missles[i].y
- )
- ctx.lineTo( //левый верхний угол снаряда
- plane.missles[i].x - MISSLE_SIZEX / 2,
- plane.missles[i].y + MISSLE_SIZEX / 2
- )
- ctx.lineTo( //левый нижний угол снаряда
- plane.missles[i].x - MISSLE_SIZEX / 2,
- plane.missles[i].y + MISSLE_SIZEY
- )
- ctx.lineTo( //правый нижний угол снаряда
- plane.missles[i].x + MISSLE_SIZEX / 2,
- plane.missles[i].y + MISSLE_SIZEY
- )
- ctx.lineTo( //правый верхний угол снаряда
- plane.missles[i].x + MISSLE_SIZEX / 2,
- plane.missles[i].y + MISSLE_SIZEX / 2
- )
- ctx.closePath();
- //ctx.strokeStyle = "cyan";
- ctx.fillStyle = "cyan";
- ctx.fill();
- if (SHOW_BOUNDING) {
- drawCollision(plane.missles[i].collision,"pink");
- }
- }
- //update acceleration
- if (plane.acceleration.posx ^ plane.acceleration.negx){
- //console.log("acceleration calc")
- if (plane.acceleration.posx){
- if (plane.speedx > 0) plane.speedx = 0 //исключение "пьяного" замедления
- plane.speedx -= PLANE_ACCELERATION;
- }
- if (plane.acceleration.negx) {
- if (plane.speedx < 0) plane.speedx = 0 //исключение "пьяного" замедления
- plane.speedx += PLANE_ACCELERATION;
- }
- } else {
- plane.speedx = 0;
- }
- //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)
- }
- }
- plane.x -= plane.speedx;
-
- /*
- if ((plane.x - plane.speedx) <= (rightBorder - plane.r) && (plane.x - plane.speedx) >= (0 + plane.r))
- { plane.x -= plane.speedx;
- } else {
- if ((plane.x - plane.speedx) > (rightBorder - plane.r)){
- plane.x =(rightBorder - plane.r);
- } else {
- if ((plane.x - plane.speedx) < (leftBorder + plane.r)) {
- plane.x = (leftBorder + plane.r);
- }
- }
- }
- */
- plane.collision.x = plane.x + 4 / 3 * plane.r * Math.cos(plane.a) - PLANE_SIZE / 2;
- plane.collision.y = plane.y - 4 / 3 * plane.r * Math.sin(plane.a)
- //двигаем снаряды
- for (var i = plane.missles.length - 1; i >= 0 ; i--) {
- if (plane.missles[i].y < 0 - MISSLE_SIZEY) { //удаление снарядов за экраном
- plane.missles.splice(i,1);
- continue;
- }
- plane.missles[i].y -= MISSLE_SPEED;
- plane.missles[i].collision.x = plane.missles[i].x - MISSLE_SIZEX / 2;
- plane.missles[i].collision.y = plane.missles[i].y;
- }
- if (plane.reload) { //перезарядка
- if (plane.reloadtime <= 0){
- console.log("reloaded");
- plane.reload = false;
- } else {
- plane.reloadtime--;
- }
- }
- }
- </script>
- </body>
- </html>
|