前言
贪吃蛇游戏是一种经典的电子游戏,玩家需要控制一条蛇去吃各种食物,使之变得越来越长,并避免撞到自己的身体或墙壁。随着吃到的食物越来越多,蛇的速度也会加快,玩家需要不断调整蛇的方向来避免失败。贪吃蛇游戏可以在电脑、手机、游戏机等不同平台上玩,是一款简单而又有趣的休闲游戏。
一、贪吃蛇游戏
好的,以下是一个完整的WebGL贪吃蛇游戏的实现。在这个实现中,我们将使用键盘控制蛇的移动,并让蛇吃到食物时变长。
HTML代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<style>
html,body{
height: 100%;
margin: 0;
text-align: center;
}
canvas{
width: 600px;
height: 600px;
margin-top: 100px;
background-color: aqua;
}
</style>
<body>
<canvas></canvas>
<div>
<button id="start">开始</button>
<button id="stop">暂停</button>
</div>
</body>
</html>
JavaScript代码:
<script>
const canvas = document.querySelector('canvas');
const gl = canvas.getContext('webgl');
// 顶点着色器源码
const vertexShaderSource = `
attribute vec4 aPostion;
void main(){
gl_Position = aPostion;
gl_PointSize = 5.0;
}
`
// 片元着色器源码
const fragmentShaderSource = `
void main(){
gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}
`
// 初始化着色器
function initShader(gl,vertexShaderSource,fragmentShaderSource){
// 创建顶点着色器
const vertexShader = gl.createShader(gl.VERTEX_SHADER);
// 创建片元着色器
const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
// 为着色器添加源码
gl.shaderSource(vertexShader, vertexShaderSource);
gl.shaderSource(fragmentShader, fragmentShaderSource);
// 编译着色器
gl.compileShader(vertexShader);
gl.compileShader(fragmentShader);
// 创建程序
const program = gl.createProgram();
// 为程序添加着色器
gl.attachShader(program,vertexShader);
gl.attachShader(program,fragmentShader);
// 建立联系
gl.linkProgram(program);
// 使用程序
gl.useProgram(program);
return program;
}
const program = initShader(gl,vertexShaderSource,fragmentShaderSource);
// 获取attribute参数
const aPostion = gl.getAttribLocation(program,'aPostion');
// 蛇
const points = [{
x:0,y:0}];
// 当前的点
const point = {
isConnect:true
}
const ERROR_SIZE = 0.03;
const BASE_STEP = 0.03;
// 每步走多少
let step = BASE_STEP;
// 方向
let direction = 'x';
let timer = null;
// 生成点
const createPoint = () => {
if(point.isConnect){
point.x = Math.random()*2 - 1;
point.y = Math.random()*2 - 1;
point.isConnect = false;
}
}
document.onkeydown = e => {
switch(e.keyCode){
case 37:
direction = 'x';
step = -1 * BASE_STEP;
break;
case 38:
direction = 'y';
step = BASE_STEP;
break;
case 39:
direction = 'x';
step = BASE_STEP;
break;
case 40:
direction = 'y';
step = -1 * BASE_STEP;
break;
}
}
const draw = () => {
// 绘制食物
gl.vertexAttrib4f(aPostion,point.x,point.y,0.0,1.0);
gl.drawArrays(gl.POINTS,0,1);
// 蛇需要动,那么就需要改变头的位置,并且后面的位置要为一到上一个位置
let prex = 0;
let prey = 0;
// 绘制蛇
for(let i = 0; i < points.length ; i++){
if(i === 0){
// 头部的位置通过位移解决
prex = points[0].x;
prey = points[0].y;
points[0][direction] += step;
}else{
const {
x, y } = points[i];
points[i].x = prex;
points[i].y = prey;
prex = x;
prey = y;
}
// 画蛇
gl.vertexAttrib4f(aPostion,points[i].x,points[i].y,0.0,1.0);
gl.drawArrays(gl.POINTS,0,1);
}
}
// 开始
const start = () => {
createPoint();
// 需要让蛇动起来
timer = setInterval(()=>{
if(points[0].x > 1.0 ||
points[0].x < -1.0 ||
points[0].y > 1.0 ||
points[0].y < -1.0
){
// 游戏结束
alert('游戏结束')
reast();
return ;
}
// 如果在误差范围内则命中
if(points[0].x < point.x + ERROR_SIZE &&
points[0].x > point.x - ERROR_SIZE &&
points[0].y < point.y + ERROR_SIZE &&
points[0].y > point.y - ERROR_SIZE
){
points.push({
x:point.x,y:point.y});
point.isConnect = true;
createPoint();
}
// 需要去绘制
draw()
},100)
}
// 重置
const reast = () => {
timer && clearInterval(timer);
points = [{
x:0,y:0}];
point = {
isConnect:true
}
step = BASE_STEP;
direction = 'x';
}
document.querySelector('#start').addEventListener('click',()=>{
start();
})
document.querySelector('#stop').addEventListener('click',()=>{
timer && clearInterval(timer);
})
</script>
在这个实现中,我们添加了一个食物对象,并在每个更新周期检查蛇是否吃到了食物。如果蛇吃到了食物,我们就让蛇变长,并在一个新的位置生成一个新的食物。
我们还添加了一个事件监听器,以便在按下箭头键时改变蛇的方向。