xxxxxxxxxx
327
let canvasWidth = 640;
let canvasHeight = 640;
let hero = {};
let heroSpeed = 2;
let heroLeftBounds;
let heroRightBounds;
let shootRequested = false;
let bullets = [];
let bulletSpeed = 4;
let bulletSize = 20;
let enemies = [];
let enemyWidth = 20;
let enemyHeight = 20;
function setup()
{
createCanvas(canvasWidth, canvasHeight);
rectMode(CENTER);
hero.x = width / 2;
hero.y = height - 50;
hero.width = 80;
hero.height = 50;
heroLeftBounds = hero.width / 2 + 10;
heroRightBounds = width - heroLeftBounds;
CreateEnemies();
}
function CreateEnemies()
{
let rows = 5;
let spacing = 30 + enemyHeight;
let startingY = 50;
for (let i = 0; i < rows; ++i)
{
let y = startingY + i * spacing;
CreateEnemyRow(y);
}
}
function CreateEnemyRow(y)
{
let count = 11;
let spacing = 30 + enemyWidth;
let rowWidth = (count - 1) * spacing;
let startingX = (width - rowWidth) / 2;
for (let i = 0; i < count; ++i)
{
let x = startingX + i * spacing;
CreateEnemy(x, y);
}
}
function draw()
{
background(220);
MoveHero();
CheckShooting();
UpdateBullets();
UpdateEnemies();
CollisionDetection();
DrawScene();
}
function keyPressed()
{
if (keyCode === 32 || // Spacebar
keyCode === UP_ARROW ||
keyCode === 87) // W
shootRequested = true;
}
function CreateEnemyAtRandomPosition()
{
let x = random(heroLeftBounds, heroRightBounds);
let y = random(30, hero.y - (hero.height / 2 + 50));
CreateEnemy(x, y);
}
function CreateEnemy(x, y)
{
let enemy = {};
enemy.x = x;
enemy.y = y;
enemy.width = enemyWidth;
enemy.height = enemyHeight;
enemies.push(enemy);
return enemy;
}
function MoveHero()
{
let xInput = 0;
if (keyIsDown(RIGHT_ARROW) || keyIsDown(68)) // D
xInput += 1;
if (keyIsDown(LEFT_ARROW) || keyIsDown(65)) // A
xInput -= 1;
hero.x += xInput * heroSpeed;
if (hero.x < heroLeftBounds)
hero.x = heroLeftBounds;
if (hero.x > heroRightBounds)
hero.x = heroRightBounds;
}
function CheckShooting()
{
if (shootRequested)
{
shootRequested = false;
Shoot();
}
}
function Shoot()
{
let bullet = CreateBullet(hero.x);
}
function CreateBullet(x)
{
let bullet = {};
bullet.x = x;
bullet.y = hero.y;
bullet.radius = bulletSize / 2;
bullets.push(bullet);
return bullet;
}
function UpdateBullets()
{
for (const bullet of bullets)
{
bullet.y -= bulletSpeed;
if (bullet.y < bullet.height / 2)
bullet.destroyed = true;
}
let newBulletArray = [];
for (const bullet of bullets)
{
if (!bullet.destroyed)
newBulletArray.push(bullet);
}
bullets = newBulletArray;
}
function UpdateEnemies()
{
let newEnemyArray = [];
for (const enemy of enemies)
{
if (!enemy.destroyed)
newEnemyArray.push(enemy);
}
enemies = newEnemyArray;
}
function CollisionDetection()
{
for (const bullet of bullets)
{
for (const enemy of enemies)
{
let enemyHalfWidth = enemy.width / 2;
let enemyHalfHeight = enemy.height / 2;
let enemyR = enemy.x + enemyHalfWidth;
let enemyL = enemy.x - enemyHalfWidth;
let enemyB = enemy.y + enemyHalfHeight;
let enemyT = enemy.y - enemyHalfHeight;
if (CircleVsRect(bullet.x, bullet.y, bullet.radius,
enemyR, enemyL, enemyB, enemyT))
{
enemy.destroyed = true;
bullet.destroyed = true;
}
}
}
}
function CircleVsRect(circleX, circleY, circleR,
rectR, rectL, rectB, rectT)
{
// If the circle
if (PointVsRect(circleX, circleY,
rectR, rectL, rectB, rectT))
return true;
// If the circle center is not inside the rectangle,
// then it's in one of the eight other regions around it.
// In such a case, we need to find the point in the rectangle
// that is nearest to the circle. If that point is inside
// the circle, then the two shapes overlap.
let nearestX;
let nearestY;
// If the circle center is to the right of the rectangle,
// then the X of the nearest point is the right edge
if (circleX > rectR)
nearestX = rectR;
// If the circle center is to the left of the rectangle,
// then the X of the nearest point is the left edge
else if (circleX < rectL)
nearestX = rectL;
// If the circle center is neither to the right nor the left,
// then the X of the nearest point is the circle center's X
else
nearestX = circleX;
// Apply the same logic but for the vertical measures
if (circleY > rectB)
nearestY = rectB;
else if (circleY < rectT)
nearestY = rectT;
else
nearestY = circleY;
// Once we have the X and Y of the nearest point, we
// check whether it's inside the circle!
return PointVsCircle(nearestX, nearestY,
circleX, circleY, circleR);
}
function PointVsRect(px, py, r, l, b, t)
{
return px >= l && px <= r && py >= t && py <= b;
}
function PointVsCircle(px, py, cx, cy, r)
{
let rSq = r * r;
let x = cx - px;
let y = cy - py;
let dSq = x * x + y * y;
return dSq <= rSq;
}
function DrawScene()
{
DrawHero();
DrawEnemies();
DrawBullets();
}
function DrawHero()
{
stroke(255, 0, 0);
fill(0);
strokeWeight(6);
rect(hero.x, hero.y, hero.width, hero.height);
}
function DrawEnemies()
{
for (const enemy of enemies)
DrawEnemy(enemy);
}
function DrawEnemy(enemy)
{
stroke(255, 255, 0);
fill(255, 0, 0);
strokeWeight(4);
rect(enemy.x, enemy.y, enemy.width, enemy.height);
}
function DrawBullets()
{
for (const bullet of bullets)
DrawBullet(bullet);
}
function DrawBullet(bullet)
{
stroke(255, 0, 0);
fill(255, 255, 0);
strokeWeight(2);
circle(bullet.x, bullet.y, bullet.radius * 2);
}