canvas#Interface
View Compiled
body {
margin: 0;
padding: 0;
background-color: #000;
}
View Compiled
/**
* Use the Arrow Keys Left and Right to Rotate Token,
* Use the Up Arrow to Move the Token in the Selected Direction
*/
const canvas = document.getElementById("Interface");
const isEven = (value) => (value % 2 === 0);
const getRandomInt = (min, max) => {
min = Math.ceil(min);
max = Math.floor(max);
return Math.floor(Math.random() * (max - min)) + min; //The maximum is exclusive and the minimum is inclusive
}
canvas.height = window.innerHeight;
canvas.width = window.innerWidth;
const ctx = canvas.getContext("2d");
class Cell {
constructor(x, y, w, h) {
this.x = x;
this.y = y;
this.width = w;
this.height = h;
this.magicYValue = 3.5
this.isOccupied = false;
} // close constructor
getXOffset() {
let xOffset = 0;
if (isEven(this.y)) {
xOffset = this.width / 2;
}
return (this.x * this.width) + xOffset;
} // close getXOffset
getYOffset() {
let yOffset = this.y * ((this.height / this.magicYValue) * -1);
return (this.y * this.height) + yOffset;
} // close getYOffset
getMyCenterPoint() {
return {
x: (this.getXOffset() + (this.width / 2)),
y: (this.getYOffset() + (this.height / 2))
};
} // close getMyCenterPoint
draw() {
const xPoint = this.width / 2;
const yOffsetValue = this.height / this.magicYValue;
const yPointTop = yOffsetValue;
const yPointBottom = this.height - yOffsetValue;
const thisXOffset = this.getXOffset();
const thisYOffset = this.getYOffset();
ctx.beginPath();
ctx.strokeStyle = "#333";
if (this.isOccupied) {
ctx.fillStyle = "#000";
} else {
ctx.fillStyle = "#111";
}
ctx.lineWidth = 4;
ctx.translate(thisXOffset, thisYOffset);
ctx.moveTo(xPoint, 0);
ctx.lineTo(this.width, yPointTop);
ctx.lineTo(this.width, yPointBottom);
ctx.lineTo(xPoint, this.height);
ctx.lineTo(0, yPointBottom);
ctx.lineTo(0, yPointTop);
ctx.lineTo(xPoint, 0);
ctx.stroke();
ctx.fill();
ctx.closePath();
ctx.setTransform(1, 0, 0, 1, 0, 0);
} // close draw
} // close class Cell
class ColliableObject {
constructor(name, color = "red", startX = 4, startY = 4, theMap) {
this.name = name;
this.color = color;
this.map = theMap;
this.width = 30;
this.height = 40;
this.posX = startX;
this.posY = startY;
this.isStuck = false;
this.hasHitEdge = false;
this.shouldDestroy = false;
this.shouldOccupySpace = true;
this.isHit = false;
this.map.occupyCell(this.posX, this.posY);
this.directionIndex = 0;
this.directionMap = [
{
label: "W",
value: -90
},
{
label: "SW",
value: -145
},
{
label: "SE",
value: 145
},
{
label: "E",
value: 90
},
{
label: "NE",
value: 35
},
{
label: "NW",
value: -35
}
];
} // close constructor
setDirection(value) {
let newValue = new Number(this.directionIndex);
if (value < 0) {
newValue = newValue - 1;
} else if (value > 0) {
newValue = newValue + 1;
}
if (newValue < 0) {
newValue = this.directionMap.length - 1;
} else if (newValue >= this.directionMap.length) {
newValue = 0;
}
this.directionIndex = newValue;
};
move() {
const playMap = this.map.playMap;
const currentDir = this.directionMap[this.directionIndex].label;
let newX = new Number(this.posX);
let newY = new Number(this.posY);
if (currentDir.match(/N/gi)) {
newY = newY - 1;
} else if (currentDir.match(/S/gi)) {
newY = newY + 1;
}
if (currentDir.match(/E/gi)) {
if (currentDir.match(/[NS]/gi)) {
if (!isEven(newY)) {
if (
(newY > 0) &&
(newY < playMap.length)
) {
newX = newX + 1;
}
} else {
if (newX >= playMap[newY].length) {
if (currentDir.match(/N/gi)) {
newY = newY + 1;
} else {
newY = newY - 1;
}
}
}
} else {
newX = newX + 1;
}
} else if (currentDir.match(/W/gi)) {
if (currentDir.match(/[NS]/gi)) {
if (isEven(newY)) {
newX = newX - 1;
if (newX < 0) {
if (currentDir.match(/N/gi)) {
newY = newY + 1;
} else {
newY = newY - 1;
}
}
}
} else {
newX = newX - 1;
}
}
if (newY < 0) {
newY = 0;
this.hasHitEdge = true;
} else if (newY >= playMap.length) {
newY = playMap.length - 1;
this.hasHitEdge = true;
}
if (newX < 0) {
newX = 0;
this.hasHitEdge = true;
} else if (newX >= playMap[newY].length) {
newX = playMap[newY].length - 1;
this.hasHitEdge = true;
}
if (!this.map.isCellOccupied(newX, newY)) {
if (this.shouldOccupySpace) {
this.map.clearCell(this.posX, this.posY);
this.map.occupyCell(newX, newY);
}
this.posX = newX;
this.posY = newY;
} else {
this.hasHitEdge = true;
this.isStuck = true;
}
} // close move
draw() {
const x = this.map.playMap[this.posY][this.posX].getMyCenterPoint().x;
const y = this.map.playMap[this.posY][this.posX].getMyCenterPoint().y;
const thisPath = new Path2D();
thisPath.arc(x, y, 20, 0, 2 * Math.PI);
ctx.fillStyle = this.color;
ctx.fill(thisPath);
} // close draw
} // close class ColliableObject
class Rock extends ColliableObject {
constructor(name, color = "Grey", startX = 4, startY = 4, theMap) {
super(name, color, startX, startY, theMap);
} // close constructor
} // close class Rock
class Bullet extends ColliableObject {
constructor(startX = 4, startY = 4, directionIndex, theMap) {
super("bullet", "Red", startX, startY, theMap);
this.directionIndex = directionIndex;
this.shouldOccupySpace = false;
this.interval = setInterval(() => {
this.move();
if (this.hasHitEdge) {
this.shouldDestroy = true;
clearInterval(this.interval);
} else {
DrawAssets.forEach(asset => {
if (
(asset.posX === this.posX) &&
(asset.posY === this.posY)
) {
asset.isHit = true;
}
})
}
}, 150)
} // close constructor
draw() {
const x = this.map.playMap[this.posY][this.posX].getMyCenterPoint().x;
const y = this.map.playMap[this.posY][this.posX].getMyCenterPoint().y;
const thisPath = new Path2D();
thisPath.arc(x, y, 5, 0, 2 * Math.PI);
ctx.fillStyle = this.color;
ctx.fill(thisPath);
} // close draw
} // close class Rock
class Ship extends ColliableObject {
constructor(name, color = "red", startX = 4, startY = 4, theMap) {
super(name, color, startX, startY, theMap);
} // close constructor
shoot() {
const bullet = new Bullet(this.posX, this.posY, this.directionIndex, this.map);
bullet.move();
DrawAssets.push(bullet);
this.map.occupyCell(this.posX, this.posY);
} // close bullet
draw() {
const x = this.map.playMap[this.posY][this.posX].getMyCenterPoint().x;
const y = this.map.playMap[this.posY][this.posX].getMyCenterPoint().y;
const yOffset = (this.height / 2);
const xOffset = (this.width / 2);
const xOffset2 = (this.width / 8);
const degree = this.directionMap[this.directionIndex].value;
ctx.beginPath();
ctx.fillStyle = this.color;
if (this.isHit) {
this.fillStyle = "Red";
}
ctx.translate(x, y);
ctx.rotate(degree * Math.PI / 180);
ctx.moveTo((xOffset2 * -1), (yOffset * -1));
ctx.lineTo(xOffset2, (yOffset * -1));
ctx.lineTo(xOffset, yOffset);
ctx.lineTo((xOffset * -1), yOffset);
ctx.closePath();
ctx.fill();
ctx.setTransform(1, 0, 0, 1, 0, 0);
} // close draw
} // close class Ship
class Map {
constructor(numCols, numRows) {
this.playMap = [];
this.numCols = numCols;
this.numRows = numRows;
this.occupationMap = [];
this.populateMap();
} // close constructor
occupyCell(x, y) {
this.playMap[y][x].isOccupied = true;
this.occupationMap.push({ x: x, y: y });
}
clearCell(x, y) {
this.playMap[y][x].isOccupied = false;
this.occupationMap = this.occupationMap.filter((value) => {
return !(
(value.x === x) &&
(value.y === y)
);
});
}
isCellOccupied(x, y) {
return this.playMap[y][x].isOccupied;
}
populateMap() {
const cellWidth = canvas.width / (this.numCols + 1);
const cellHeight = (canvas.height / this.numRows) * 1.34;
this.playMap = [];
for (let y = 0; y < this.numRows; y++) {
let thisRow = [];
for(let x = 0; x < this.numCols; x++) {
thisRow.push(new Cell(x, y, cellWidth, cellHeight));
}
if (!isEven(y)) {
thisRow.push(new Cell(this.numCols, y, cellWidth, cellHeight));
}
this.playMap.push(thisRow);
}
this.occupationMap.forEach(record => {
this.playMap[record.y][record.x].isOccupied = true;
});
} // close populateMap
draw() {
for (let y = 0; y < this.playMap.length; y++) {
for(let x = 0; x < this.playMap[y].length; x++) {
const cell = this.playMap[y][x];
cell.draw();
}
}
} // close draw
} // close class Map
const gridX = 9;
const gridY = 9;
const theMap = new Map(gridX, gridY);
const myShip = new Ship("Intrepid", "green", 4, 4, theMap);
const targetShip = new Ship("Sential", "blue", 2,7, theMap);
let isAnimating = false;
let isSentinalRunning = false;
let DrawAssets = [
myShip,
targetShip
];
function animation() {
isAnimating = true;
requestAnimationFrame(animation);
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = "#090000";
ctx.fillRect(0, 0, canvas.width, canvas.height);
theMap.draw();
DrawAssets = DrawAssets.filter(asset => !asset.shouldDestroy);
DrawAssets.forEach(asset => {
asset.draw();
});
} // close animation()
const sentinalRun = () => {
isSentinalRunning = true;
setTimeout(function() {
const rndValue = getRandomInt(-1, 1);
if (rndValue === 0) {
targetShip.move(0);
} else {
targetShip.setDirection(rndValue);
}
sentinalRun();
}, 500);
} // close sentinalRun
const init = (numRocks = 4) => {
DrawAssets = [
myShip,
targetShip
];
let RockCount = 0;
while (RockCount < numRocks) {
const randomX = getRandomInt(0, gridX - 1);
const randomY = getRandomInt(0, gridY - 1);
if (!theMap.isCellOccupied(randomX, randomY)) {
DrawAssets.push(new Rock(`Rock ${RockCount}`,"gray",randomX, randomY, theMap));
RockCount++;
}
}
if (!isAnimating) {
animation();
}
if (!isSentinalRunning) {
sentinalRun();
}
} // close init
document.addEventListener("keydown", (event) => {
const key = event.key;
// console.log(key);
if (key === "ArrowLeft") {
myShip.setDirection(1);
} else if (key === "ArrowRight") {
myShip.setDirection(-1);
} else if (key === "ArrowUp") {
myShip.move();
} else if (key === " ") {
myShip.shoot();
}
}); // close addEventListener(keydown)
window.addEventListener("resize", () => {
canvas.height = window.innerHeight;
canvas.width = window.innerWidth;
theMap.populateMap();
}); // close addEventListener(resize)
init(4);
View Compiled
This Pen doesn't use any external CSS resources.
This Pen doesn't use any external JavaScript resources.