1 Star 0 Fork 0

CoderMeow/Snake Game

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
main.js 6.22 KB
一键复制 编辑 原始数据 按行查看 历史
CoderMeow 提交于 2025-01-30 18:47 +08:00 . upload.
'use strict';
/** This is the init setting of game. */
const canvas = document.getElementById("game-canvas");
const score_element = document.getElementById("game-score");
const snake_body_color = "#cf2128";
const snake_head_color = "#ef3148";
const food_color = "#1faf0f";
const default_head_pos = [11, 10];
const default_body_len = 1;
const default_direct = 'r';
const difficulty = 200;
const map_width = 20;
const move_key = {
'r':{
'key': 'x',
'step': 1
},
'l':{
'key': 'x',
'step': -1
},
'u':{
'key': 'y',
'step': -1
},
'd':{
'key': 'y',
'step': 1
}
}
const direct_key = {
'ArrowRight':'r',
'ArrowLeft':'l',
'ArrowUp':'u',
'ArrowDown':'d',
'w':'u',
'a':'l',
'd':'r',
's':'d'
}
const prevent_key = {
'r':'l',
'l':'r',
'u':'d',
'd':'u'
}
/** The Game Attribute Model */
function Game_Attr(a, b, c) {
this.snake_body_color = a;
this.snake_head_color = b;
this.food_color = c;
}
/** The Vec model(To mark position and direction) */
class Vec{
constructor(x, y){
this.x = x?x:0, this.y = y?y:0;
}
copy(a){
this.x = a.x, this.y = a.y;
}
equal(a){
return this.x == a.x&&this.y == a.y;
}
//Other methods... (Maybe will be created in the future)
}
/** The Snake Model */
class Snake{
constructor(){
this.body_units = new Array();
this.head = new Vec(default_head_pos[0], default_head_pos[1]);
}
}
/** The Game State Model */
function Game_State() {
this.direction = default_direct; //Snake's direction (left: l |right: r |up: u |down: d)
this.score = 0;
this.snake = new Snake();
this.food_pos = new Vec();
this.key_queue = new Array();
}
/** The renderer class */
class Renderer{
constructor(canvas, snake){
//TODO: The renderer class should be finished.
this.canvas = canvas;
this.canvas_ctx = canvas.getContext("2d");
}
render(snake, score, food_pos){
this.clean();
this.drawSnake(snake);
this.drawFood(food_pos);
//render score
score_element.innerText = score;
}
drawSnake(snake){
//draw head
this.createBlock(snake.head, snake_head_color);
let a = snake.body_units;
for(let i = 0; i < a.length; i++)this.createBlock(a[i], snake_body_color);
}
drawFood(pos) {
this.createBlock(pos, food_color);
}
createBlock(pos, color){
let bx = this.canvas.width/map_width, by = this.canvas.height/map_width;
this.canvas_ctx.fillStyle=color;
this.canvas_ctx.fillRect(pos.x*bx, pos.y*by, bx, by);
}
clean() {
this.canvas_ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
}
//...
}
/** The Main Game Class */
class Game{
constructor() {
this.canvas = canvas;
this.attribute;
this.state;
this.renderer = new Renderer(canvas);
this.interval;
this.Load();
}
/** Load the basic construction */
Load(){
this.played = false;
this.listeners = new Array();
}
/** Init game method */
Init(){
this.attribute = new Game_Attr(snake_body_color, snake_head_color, food_color);
this.state = new Game_State();
//Init body
for(let i = 1; i <= default_body_len; i++){
let a = this.state.snake.head;
this.state.snake.body_units.push(new Vec(((a.x - i >= 0)?(a.x - i):(map_width - Math.abs(a.x-i)%map_width)),a.y));
}
}
/** Start the game */
Play() {
//create Game Interval
this.createFood();
this.interval = this.createInterval();
this.renderer.render(this.state.snake, this.state.score, this.state.food_pos);
this.addKeyListeners();
}
createInterval(){
return setInterval(() => {
this.moveSnake();
this.renderer.render(this.state.snake, this.state.score, this.state.food_pos);
}, difficulty);
}
moveSnake() {
if(this.state.key_queue.length>0)this.state.direction = this.state.key_queue.shift(); //change
let a = this.state.snake.head;
this.state.snake.body_units.unshift(new Vec(this.state.snake.head.x, this.state.snake.head.y));
if((a[move_key[this.state.direction].key]+move_key[this.state.direction].step)>=0)a[move_key[this.state.direction].key] = (a[move_key[this.state.direction].key]+move_key[this.state.direction].step)%20;
else a[move_key[this.state.direction].key] = 20+(a[move_key[this.state.direction].key]+move_key[this.state.direction].step)%20;
//碰撞检测
if(this.state.snake.body_units.find(e=>e.equal(this.state.snake.head))){
alert("Game Over! Your score is:"+ this.state.score);
this.reload();
}else if(this.state.snake.head.equal(this.state.food_pos)){
this.state.score++;
this.createFood();
}else if(this.state.snake.body_units.length > 1)this.state.snake.body_units.pop();
}
createFood() {
let pos;
do {
pos = new Vec(Math.floor(Math.random()*20), Math.floor(Math.random()*20));
}while(this.state.snake.body_units.find(e=>e.equal(pos)));
this.state.food_pos = pos;
}
addKeyListeners() {
let a = (ev) => {
if(prevent_key[(this.state.key_queue.length > 0)?(this.state.key_queue.at(-1)):(this.state.direction)] == direct_key[ev.key] || !direct_key[ev.key])return;
this.state.key_queue.push(direct_key[ev.key]);
};
this.listeners.push(['keyup', a]);
window.addEventListener('keyup', a);
}
reload(){
clearInterval(this.interval);
for(let i = 0; i < this.listeners.length; i++)window.removeEventListener(this.listeners[i][0], this.listeners[i][1]);
this.Load();
this.Init();
this.Play();
}
//Other Methods (Maybe will be created in the future)
};
//Main Function
(function(){
Game = new Game();
Game.Init(); //init the game
document.getElementById("start-button").addEventListener("mouseup", function(){
document.getElementById("start-page").remove();
document.getElementById("game-box").style.display = "block";
Game.Play();
})
}());
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
JavaScript
1
https://gitee.com/codemiao08/snake-game.git
git@gitee.com:codemiao08/snake-game.git
codemiao08
snake-game
Snake Game
master

搜索帮助