Html,Css,JavaScript
Html
Canvas
게임
Download: IceHockey.html
Html로 만든 아이스하키 게임 IceHockey 2P
Dec. 1, 2022, 10:41 p.m.
이 게임은 제가 군 생활 중에 만든 Html 게임 중에 가장 평이 좋았던 게임입니다. 다같이 하키 게임 하면서 시간도 녹이고 서로 리그전도 하고 하면서 재밌게 군생활을 녹였던 기억이 있네요.
밑은 코드 전문입니다. 첨부파일과 깃허브 링크도 있으니 참고하시길 바랍니다.
군대에서 대충 짜다 보니 깔끔한 코드와는 거리가 먼 것 같습니다... 약간의 디자인 적 요소는 부트스트랩을 활용했습니다.
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8" />
<title>Ice Hockey 2P</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-Zenh87qX5JnK2Jl0vWa8Ck2rdkQ2Bzep5IDxbcnCeuOxjzrPF/et3URy9Bv1WTRi" crossorigin="anonymous">
</head>
<body>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-OERcA2EqjJCMA+/3y+gxIOqMEjwtxJY7qPCqsdltbNJuaOe923+mo//f6V8Qbsw3" crossorigin="anonymous"></script>
<h3 style="text-align:center">Ice Hockey 2P</h3>
<div class="container alert alert-success text-center">
B: <kbd>W</kbd><kbd>S</kbd><kbd>A</kbd><kbd>D</kbd> 로 상하좌우, <kbd>Space</kbd>로 슛. A: <kbd>↑</kbd><kbd>↓</kbd><kbd>←</kbd><kbd>→</kbd> 로 상하좌우, <kbd>0</kbd>로 슛. 슛 버튼을 눌러 준비.
</div>
<div>
</div>
<div style="position:absolute; left:50%;margin-left:-650px;">
<canvas id="canvas" height=700, width=1300></canvas>
</div>
<script>
var width = 1300;
var height = 700;
var goalwidth = 100;
var goalbarwidth = 10;
var goaldepth = 50;
var ascore = 0;
var bscore = 0;
var apre = false;
var bpre = false;
var key = [];
var framerate = 60;
class puck {
constructor() {
this.debug = false;
this.x = width/2;
this.y = height/2;
this.v = 0;
this.theta = 0;
this.vx = 0;
this.vy = 0;
this.drag = 0.1;
this.r = 10;
this.captured = false;
this.capturalbeV = 10;
}
reset()
{
this.x = width/2;
this.y = height/2;
this.v = 0;
this.theta = 0;
this.vx = 0;
this.vy = 0;
}
angle()
{
return (360-this.theta)%360;
}
setangle(a)
{
this.theta = (360 - a)% 360;
}
update()
{
if (!this.captured)
{
this.vx = this.v * Math.cos(Math.PI/180*this.angle());
this.vy = this.v * Math.sin(Math.PI/180*this.angle());
this.x += this.vx;
this.y += this.vy;
c1.captured = false;
c2.captrued = false;
if (this.v > 0)
{
this.v -= this.drag;
}
else
{
this.v = 0;
}
if (this.y > height - this.r)
{
if (this.angle() >= 0 && this.angle() < 180)
{
this.setangle(360 - this.angle());
}
}
if (this.y < this.r)
{
if (this.angle() >=180 && this.angle() < 360)
{
this.setangle(360 - this.angle());
}
}
if (this.x < goaldepth+this.r)
{
if((this.y>height/2-goalwidth/2)&&(height/2+goalwidth/2>this.y))
{
console.log("goal!@!");
bscore++;
if (bscore > 4)
{
alert("B side wins!");
reset();
ascore = 0;
bscore = 0;
}
reset();
}
if (this.angle()>=90&&this.angle()<270)
{
this.setangle(180 - this.angle());
}
}
if (this.x>width-goaldepth-this.r)
{
if((this.y>height/2-goalwidth/2)&&(height/2+goalwidth/2>this.y))
{
console.log("goal!@!");
ascore++;
if (ascore > 4)
{
alert("A side wins!");
reset();
ascore = 0;
bscore = 0;
}
reset();
}
if((this.angle()>=0&&this.angle()<90)||(this.angle()>=270&&this.angle()<360))
{
this.setangle(180 - this.angle());
}
}
}
else
{
this.v = 0;
this.x = this.captured.x + (this.captured.r+this.r) * Math.cos(this.captured.angle);
this.y = this.captured.y - (this.captured.r+this.r) * Math.sin(this.captured.angle);
}
}
draw()
{
ctx.fillStyle = "black";
ctx.beginPath();
ctx.arc(this.x, height-this.y, this.r, 0, Math.PI * 2);
ctx.fill();
if (this.debug)
{
ctx.beginPath();
ctx.moveTo(this.x, height - this.y);
ctx.lineTo(this.x+100*Math.cos(Math.PI/180*this.angle()), height-(this.y+100*Math.sin(Math.PI/180*this.angle())));
ctx.stroke();
}
}
}
class char {
constructor()
{
this.r = 30;
this.vx = 0;
this.vy = 0;
this.drag = 0.1;
this.a = 0.3;
this.angle = 0;
this.x = width/3;
this.y = height/2;
this.color = "blue";
this.debug = true;
this.maxv = 20;
this.range = 15;
this.power = 0;
this.maxpower = 30;
this.powerv = 0.5;
this.pressed = false;
this.captured = false;
this.keys = [38, 40, 37, 39, 96];
}
reset()
{
this.x = width/3;
this.y = height/2;
this.vx = 0;
this.vy = 0;
this.angle = 0;
}
draw()
{
ctx.fillStyle = this.color;
ctx.beginPath();
ctx.arc(this.x, height - this.y, this.r, 0, Math.PI * 2);
ctx.fill();
if (this.power > 0)
{
ctx.fillStyle = this.color;
ctx.beginPath();
ctx.arc(this.x+this.r*Math.cos(this.angle), height - (this.y-this.r*Math.sin(this.angle)), this.power*2, this.angle - Math.PI/16, this.angle + Math.PI/16, false);
ctx.lineTo(this.x+this.r*Math.cos(this.angle), height - (this.y-this.r*Math.sin(this.angle)));
ctx.closePath();
ctx.fill();
}
ctx.fillStyle = "black";
ctx.beginPath();
ctx.arc(this.x, height - this.y, 25, this.angle - Math.PI/8, this.angle + Math.PI/8, false);
ctx.lineTo(this.x, height - this.y);
ctx.closePath();
ctx.fill();
}
update()
{
if(key[this.keys[2]]){this.vx-=this.a;}
if(key[this.keys[0]]){this.vy+=this.a;}
if(key[this.keys[3]]){this.vx+=this.a;}
if(key[this.keys[1]]){this.vy-=this.a;}
this.x += this.vx;
this.y += this.vy;
if(this.vx>0)
{
this.angle = Math.atan(-1*this.vy/this.vx);
}
else if(this.vx < 0)
{
this.angle = Math.atan(-1*this.vy/this.vx) + Math.PI;
if (!this.angle)
this.angle = 0;
}
else
{
if (this.vx == 0)
{
if(this.vy > 0)
{
this.angle = Math.PI * 3 / 2;
}
else if (this.vy < 0)
{
this.angle = Math.PI/2;
}
}
}
if (this.vx > this.maxv)
{
this.vx = this.maxv;
}
else if (this.vx > 0.2)
{
this.vx -= this.drag;
}
else if (this.vx < -this.maxv)
{
this.vx = -this.maxv;
}
else if (this.vx < -0.2)
{
this.vx += this.drag;
}
else
{
this.vx = 0;
}
if (this.vy > this.maxv)
{
this.vy = this.maxv;
}
else if (this.vy > 0.2)
{
this.vy -= this.drag;
}
else if (this.vy < -this.maxv)
{
this.vy = -this.maxv;
}
else if (this.vy < -0.2)
{
this.vy += this.drag;
}
else
{
this.vy = 0;
}
if (this.y - this.r < 0)
{
if (this.vy < 0)
this.vy *= -0.5;
}
if(this.y + this.r > height)
{
if(this.vy > 0)
this.vy *= -0.5;
}
if(this.x-this.r < goaldepth)
{
if(this.vx < 0)
this.vx *= -0.5;
}
if(this.x+this.r > width-goaldepth)
{
if(this.vx > 0)
this.vx *= -0.5;
}
if (this.captured!=false)
{
if (key[this.keys[4]])
{
if (!this.pressed)
{
this.pressed = true;
}
this.a = 0.3;
this.maxv = 15;
if (this.power < this.maxpower)
{
this.power += this.powerv;
}
}
else if (!key[this.keys[4]])
{
if (this.pressed)
{
p.v = this.power;
p.setangle(this.angle/Math.PI*180*-1);
this.captrued = false;
p.captured = false;
}
this.a = 0.3;
this.maxv = 20;
this.pressed = false;
this.power = 0;
}
}
else
{
this.power = 0;
this.pressed = false;
}
}
}
function reset()
{
c1.reset();
c2.reset();
p.reset();
c1.x = width/3*2;
bpre = false;
apre = false;
drawmap(false);
c1.draw();
c2.draw();
}
function drawmap(score=true)
{
ctx.fillStyle = "white";
ctx.fillRect(0, 0, width, height);
ctx.fillStyle = "black";
ctx.fillRect(goaldepth, 0, width-goaldepth*2, height);
ctx.fillStyle = "white";
ctx.fillRect(goaldepth+3, 3, width-goalwidth-6, height - 6);
ctx.fillRect(goaldepth, height/2-goalwidth/2, width, goalwidth);
ctx.fillStyle = "red";
ctx.beginPath();
ctx.arc(width/2, height/2, 78, 0, Math.PI*2);
ctx.fill();
ctx.fillStyle = "white";
ctx.beginPath();
ctx.arc(width/2, height/2, 75, 0, Math.PI * 2);
ctx.fill();
ctx.fillStyle ="red";
ctx.fillRect(width/2-1.5, 3, 3, height-6);
ctx.fillStyle = "black";
ctx.fillRect(0, height/2-goalwidth/2-goalbarwidth, goaldepth, goalbarwidth);
ctx.fillRect(0, height/2+goalwidth/2, goaldepth, goalbarwidth);
ctx.fillRect(width-goaldepth, height/2-goalwidth/2-goalbarwidth, goaldepth, goalbarwidth);
ctx.fillRect(width-goaldepth, height/2+goalwidth/2, goaldepth, goalbarwidth);
if (score)
{
ctx.fillStyle = "black";
ctx.font = "40px Arial";
ctx.fillText(ascore, width/4, 40);
ctx.fillText(bscore, width * 3 / 4, 40);
}
}
var interval = setInterval(function()
{
game();
}, 1000/framerate);
var canvas = document.getElementById("canvas");
canvas.style.border = "1px, solid black";
var ctx = canvas.getContext("2d");
var p = new puck();
var c1 = new char();
var c2 = new char();
c1.x = width/3*2;
c2.color="red";
c2.x = width/3;
c2.keys=[87, 83, 65, 68, 32];
reset();
function game()
{
if(apre&&bpre)
{
drawmap(true);
c2.update();
c2.draw();
c1.update();
c1.draw();
p.update();
p.draw();
calCollision();
}
else
{
if (apre)
{
ctx.fillStyle = "black";
ctx.font = "40px Arial";
ctx.fillText("A Ready", width*3/4, 40);
}
if (bpre)
{
ctx.fillStyle = "black";
ctx.font = "40px Arial";
ctx.fillText("B Ready", width/4, 40);
}
if(key[c1.keys[4]])
{
apre = true;
}
if(key[c2.keys[4]])
{
bpre = true;
}
}
}
function calCollision()
{
var c = 1;
function d(a, b)
{
return Math.sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
function cold(a, b)
{
return a.r+b.r;
}
if(d(p, c1)<=cold(p, c1))
{
var dv = Math.abs(Math.sqrt((p.v*Math.cos(p.angle())-c1.vx)*(p.v*Math.cos(p.angle())-c1.vx)+(p.v*Math.sin(p.angle())-c1.vy)*(p.v*Math.sin(p.angle())-c1.vy)));
if (dv > this.capturalbeV)
{
var ratio = (cold(p, c1) - d(p, c1)) / d(p, c1);
var dx = (p.x - c1.x) * ratio;
var dy = (p.y - c1.y) * ratio;
c1.x -= dx;
c1.y -= dy;
var pvx = (p.r*p.r*p.vx+2*c1.r*c1.r*cl.vx-c1.r*c1.r*p.vx) / (p.r*p.r+c1.r*c1.r);
var pvy = (p.r*p.r*p.vy+2*c1.r*c1.r*c1.vy-c1.r*c1.r*p.vy) / (p.r*p.r+c1.r*c1.r);
if (pvx > 0)
{
p.setangle(Math.atan(pvy/pvx) / Math.PI*180);
}
else
{
p.setangle(Math.atan(pvy/pvx) / Math.PI*180 + 180);
}
p.v = Math.sqrt(pvx*pvx+pvy*pvy)*c;
c1.vx = (c1.r*c1.r*c1.vx+2*p.r*p.r*p.vx-p.r*p.r*c1.vx) / (p.r*p.r+c1.r*c1.r);
c1.vy = (c1.r*c1.r*c1.vy+2*p.r*p.r*p.vy-p.r*p.r*c1.vy) / (p.r*p.r+c1.r*c1.r);
}
else
{
if(!p.captured)
{
p.captured = c1;
c1.captured = true;
}
}
}
if(d(p, c2)<=cold(p, c2))
{
var dv = Math.abs(Math.sqrt((p.v*Math.cos(p.angle())-c2.vx)*(p.v*Math.cos(p.angle())-c2.vx)+(p.v*Math.sin(p.angle())-c2.vy)*(p.v*Math.sin(p.angle())-c2.vy)));
if (dv > this.capturalbeV)
{
var ratio = (cold(p, c2) - d(p, c2)) / d(p, c2);
var dx = (p.x - c2.x) * ratio;
var dy = (p.y - c2.y) * ratio;
c2.x -= dx;
c2.y -= dy;
var pvx = (p.r*p.r*p.vx+2*c2.r*c2.r*c2.vx-c2.r*c2.r*p.vx) / (p.r*p.r+c2.r*c2.r);
var pvy = (p.r*p.r*p.vy+2*c2.r*c2.r*c2.vy-c2.r*c2.r*p.vy) / (p.r*p.r+c2.r*c2.r);
if (pvx > 0)
{
p.setangle(Math.atan(pvy/pvx) / Math.PI*180);
}
else
{
p.setangle(Math.atan(pvy/pvx) / Math.PI*180 + 180);
}
p.v = Math.sqrt(pvx*pvx+pvy*pvy)*c;
c2.vx = (c2.r*c2.r*c2.vx+2*p.r*p.r*p.vx-p.r*p.r*c2.vx) / (p.r*p.r+c2.r*c2.r);
c2.vy = (c2.r*c2.r*c2.vy+2*p.r*p.r*p.vy-p.r*p.r*c2.vy) / (p.r*p.r+c2.r*c2.r);
}
else
{
if(!p.captured)
{
p.captured = c2;
c2.captured = true;
}
}
}
if(d(c1, c2)<=cold(c1, c2))
{
var ratio = (cold(c1, c2) - d(c1, c2)) / d(c1, c2);
var dx = (c1.x - c2.x) * ratio;
var dy = (c1.y - c2.y) * ratio;
c2.x -= dx;
c2.y -= dy;
c1.x += dx;
c1.y += dy;
var c2vx = (2*c1.r*c1.r*c1.vx) / (c1.r*c1.r + c2.r*c2.r);
var c2vy = (2*c1.r*c1.r*c1.vy) / (c1.r*c1.r + c2.r*c2.r);
var c1vx = (2*c2.r*c2.r*c2.vx) / (c1.r*c1.r + c2.r*c2.r);
var c1vy = (2*c2.r*c2.r*c2.vy) / (c1.r*c1.r + c2.r*c2.r);
c1.vx = c1vx;
c1.vy = c1vy;
c2.vx = c2vx;
c2.vy = c2vy;
p.captured = false;
}
}
window.addEventListener("keydown", function(e){
key[e.keyCode]=true;
});
window.addEventListener("keyup", function(e){
key[e.keyCode]=false;
})
</script>
</body>
</html>
Download: IceHockey.html
Html,Css,JavaScript 의 다른 글 보기
pHqghUme
555
Jan. 22, 2025, 7:53 a.m.
pHqghUme
555
Jan. 22, 2025, 7:53 a.m.
pHqghUme
555
Jan. 22, 2025, 7:53 a.m.
pHqghUme
-1 OR 2+289-289-1=0+0+0+1 --
Jan. 22, 2025, 7:53 a.m.
pHqghUme
-1 OR 2+861-861-1=0+0+0+1
Jan. 22, 2025, 7:53 a.m.
pHqghUme
-1' OR 2+306-306-1=0+0+0+1 --
Jan. 22, 2025, 7:53 a.m.
pHqghUme
-1' OR 2+157-157-1=0+0+0+1 or 'VsqSwJip'='
Jan. 22, 2025, 7:53 a.m.
pHqghUme
-1" OR 2+880-880-1=0+0+0+1 --
Jan. 22, 2025, 7:53 a.m.
pHqghUme
555*if(now()=sysdate(),sleep(15),0)
Jan. 22, 2025, 7:53 a.m.
pHqghUme
5550'XOR(555*if(now()=sysdate(),sleep(15),0))XOR'Z
Jan. 22, 2025, 7:53 a.m.
pHqghUme
5550"XOR(555*if(now()=sysdate(),sleep(15),0))XOR"Z
Jan. 22, 2025, 7:53 a.m.
pHqghUme
(select(0)from(select(sleep(15)))v)/*'+(select(0)from(select(sleep(15)))v)+'"+(select(0)from(select(sleep(15)))v)+"*/
Jan. 22, 2025, 7:53 a.m.
pHqghUme
555-1; waitfor delay '0:0:15' --
Jan. 22, 2025, 7:53 a.m.
pHqghUme
555-1); waitfor delay '0:0:15' --
Jan. 22, 2025, 7:53 a.m.
pHqghUme
555-1 waitfor delay '0:0:15' --
Jan. 22, 2025, 7:53 a.m.
pHqghUme
5559tDpvSHx'; waitfor delay '0:0:15' --
Jan. 22, 2025, 7:53 a.m.
pHqghUme
555-1 OR 895=(SELECT 895 FROM PG_SLEEP(15))--
Jan. 22, 2025, 7:53 a.m.
pHqghUme
555-1) OR 734=(SELECT 734 FROM PG_SLEEP(15))--
Jan. 22, 2025, 7:53 a.m.
pHqghUme
555-1)) OR 597=(SELECT 597 FROM PG_SLEEP(15))--
Jan. 22, 2025, 7:53 a.m.
pHqghUme
555E2OaBJDx' OR 222=(SELECT 222 FROM PG_SLEEP(15))--
Jan. 22, 2025, 7:53 a.m.
pHqghUme
555S6mM6MbH') OR 241=(SELECT 241 FROM PG_SLEEP(15))--
Jan. 22, 2025, 7:53 a.m.
pHqghUme
5557StVmpv5')) OR 535=(SELECT 535 FROM PG_SLEEP(15))--
Jan. 22, 2025, 7:53 a.m.
pHqghUme
555*DBMS_PIPE.RECEIVE_MESSAGE(CHR(99)||CHR(99)||CHR(99),15)
Jan. 22, 2025, 7:53 a.m.
pHqghUme
555'||DBMS_PIPE.RECEIVE_MESSAGE(CHR(98)||CHR(98)||CHR(98),15)||'
Jan. 22, 2025, 7:53 a.m.
pHqghUme
555
Jan. 22, 2025, 7:53 a.m.
pHqghUme
555'"
Jan. 22, 2025, 7:53 a.m.
pHqghUme
555����%2527%2522\'\"
Jan. 22, 2025, 7:53 a.m.
pHqghUme
@@7fs5c
Jan. 22, 2025, 7:53 a.m.
pHqghUme
555
Jan. 22, 2025, 7:53 a.m.
pHqghUme
555
Jan. 22, 2025, 7:53 a.m.
pHqghUme
555
Jan. 22, 2025, 7:53 a.m.