代码地址如下:
http://www.demodashi.com/demo/11818.html

贪吃蛇小游戏(第二版)

一年半前层用react写过贪吃蛇小游戏https://github.com/caohuilin/Snake_React

那时刚刚学习React的我兴奋的尝试了很久

近些日子比较清闲,想着用学到的东西重新写个版本,于是V2就来了https://github.com/caohuilin/Snake_React_v2

游戏规则

贪吃蛇大家都不陌生了,吃掉一个食物,蛇的身体会变长,食物随机出现在屏幕的另一个位置。碰到自己或者碰到墙壁游戏结束。

注意一点就是设置目前只支持游戏模式的设置。

点击设置按钮后,点击左键或者右键进行模式切换。

项目安装部署

Install

yarn install

Start Serve

It's served in http://localhost:3000 .

yarn run serve

Build

yarn run build

游戏思路介绍

基础项目搭建

采用webpack、gulp构建工具,搭建React开发脚手架

游戏界面划分

  • 设计游戏界面(游戏界面分为标题,主界面,按键三部分组成)
  • 根据划分的界面构建组件

基础组件界面实现

  • Header采用蛇身体部分元素展示
  • 主界面分为游戏屏幕界面和游戏过程中信息展示界面
  • 按键界面主要为游戏方向控制键,游戏开始键和游戏设置相关键

让蛇动起来

  • 定义snake初始值和初始方向

    snake初始值为游戏界面随机相邻的两个点
const index = modal === 1 ? 3 : 1;// modal为游戏模式
const x = Math.floor(Math.random() * (column - index)) + 1;// column为根据屏幕大小计算出的游戏界面的高度
const y = Math.floor(Math.random() * (Row - index)) + 1;// Row为游戏界面的宽度
const ISnakeRecord = Immutable.Record({
snake: Immutable.fromJS([
{
x: x,
y: y
}, {
x: x,
y: y - 1
}
])
});
const IDirectionRecord = Immutable.Record({
snake: 3
});
  • 定义设置snake的action
export const setSnack = createAction('set snake');export const setSnack = createAction('set snake');
  • 开始游戏后,每500ms计算蛇下一个的位置
//goNext函数为计算snake下一个的位置,并触发设置snake的action,组件重新加载,从而模拟蛇前进的动画。
startGame = () => {
if (this.timer ) { clearInterval(this.timer); }
this.timer = setInterval(this.goNext, 500);
}

监听按键,改变蛇的运动方向

  • 定义设置snake方向的action
export const setSnackDirection = createAction('set snake direction');
  • DOM监听KeyDown事件
<div className='app' onKeyDown={this.keyDown} tabIndex={0}>
...
</div>
  • keyDown事件的实现

    除了改变蛇的方向的按键之外,还实现了游戏开始,游戏结束,游戏暂停,重新开始游戏,设置游戏模式等按键的监听,实现方式基本差不多,只是触发不同的action,改变不同的reducer
  handleKeyDown = (code) => {
// init 为游戏当前所处状态,只有当初始化动画显示完毕开始游戏之后,方向键才起相应作用
const init = this.props.game.get('init');
if (code === 1) {
this.props.actions.setVolume();
} else if (init === 0) {// 初始化完毕
if (code === 2 || code === 0 ) {// 开始游戏
this.props.actions.setGameInit(1);
this.props.actions.clearCode();
this.props.actions.startGame();
} else if (code === 3) {// 设置游戏模式
this.props.actions.setGameInit(-2);
}
} else if (init === 1) {// 游戏中
let direction = this.props.direction.get('snake');
if (code === 38 && direction !== 1) {
direction = 0;
} else if (code === 40 && direction !== 0) {
direction = 1;
} else if (code === 37 && direction !== 3) {
direction = 2;
} else if (code === 39 && direction !== 2) {
direction = 3;
} else if (code === 32) {
this.props.actions.pauseGame();
} else if (code === 4) {
this.props.actions.pauseGame({pause: true});
} else if (code === 2) {
this.props.actions.pauseGame({pause: false});
this.props.actions.startGame();
} else if (code === 0) {
this.props.actions.endGame();
this.props.actions.setGameInit(-1);
this.props.actions.initSnack();
setTimeout(this.handleKeyDown.bind(null, 2), 0);
}
this.props.actions.setSnackDirection(direction);
} else if (init === -2) {// 设置游戏模式
if (code === 37 || code === 39) {
this.props.actions.setModal();
} else if (code === 2) {
this.props.actions.setGameInit(1);
this.props.actions.startGame();
}
} else if (init === -1 && code === 2) {// 初始化中
setTimeout(this.handleKeyDown.bind(null, 2), 0);
}
}
keyDown = (event: any) => {
const code = event.nativeEvent.keyCode;
this.handleKeyDown(code);
}

食物的产生

  • 初始化食物的位置
const index = modal === 1 ? 3 : 1;
const x = Math.floor(Math.random() * (column - index)) + 1;
const y = Math.floor(Math.random() * (Row - index)) + 1;
const IFoodRecord = Immutable.Record({
food: Immutable.fromJS(
{
x: x,
y: y
}
)
});
  • 定义重新设置食物位置的action
export const setFood = createAction('set food');
  • 让食物闪动起来

    每隔200ms改变食物是否显示的样式,制造食物闪动的效果
this.foodTimer = setInterval(this.setFoodShowOrHide, 200);
setFoodShowOrHide = () => {
this.setState({ showFood: !this.state.showFood});
}
<div className={`cell ${showFood ? 'food-o-cell' : 'food-cell'}`}></div>
  • 判断snake头部下一个位置是否为食物的位置,若为食物的位置,蛇的长度+1,出发重新设置食物位置的action
    if (next.x !== currentFood.x || next.y !== currentFood.y) {
currentSnake.pop();
} else {
this.props.actions.getCode();
this.props.actions.setFood();
}

分数展示

初始设置分数为0,每一次判断到snake头部下一个位置是否为食物时,分数+1

模式选择

在设置模式下,左右按键实现模式切换

试玩

https://caohuilin.github.io/Snake_React_v2/

补充

基本功能已经实现,难免有处理不当或者没有考虑到的界限问题,欢迎提Issue,https://github.com/caohuilin/Snake_React_v2

祝大家玩的愉快!

附项目文件截图



基于React的贪吃蛇游戏的设计与实现

代码地址如下:
http://www.demodashi.com/demo/11818.html

注:本文著作权归作者,由demo大师代发,拒绝转载,转载需要作者授权

基于React的贪吃蛇游戏的设计与实现的更多相关文章

  1. 用Java开发贪吃蛇游戏

    贪吃蛇游戏的设计步骤: Part 1: 设计游戏图纸 画出900*700的白色窗口 在窗口上添加画布 在画布上添加标题 在画布上添加黑色游戏区 Part 2: 放置静态的蛇:一个头.两个身体 加上开始 ...

  2. WebGL实现HTML5的3D贪吃蛇游戏

    js1k.com收集了小于1k的javascript小例子,里面有很多很炫很酷的游戏和特效,今年规则又增加了新花样,传统的classic类型基础上又增加了WebGL类型,以及允许增加到2K的++类型, ...

  3. 100行JS实现HTML5的3D贪吃蛇游戏

    js1k.com收集了小于1k的javascript小例子,里面有很多很炫很酷的游戏和特效,今年规则又增加了新花样,传统的classic类型基础上又增加了WebGL类型,以及允许增加到2K的++类型, ...

  4. Qt 学习之路 2(34):贪吃蛇游戏(4)

    Qt 学习之路 2(34):贪吃蛇游戏(4) 豆子 2012年12月30日 Qt 学习之路 2 73条评论 这将是我们这个稍大一些的示例程序的最后一部分.在本章中,我们将完成GameControlle ...

  5. Qt 学习之路 2(31):贪吃蛇游戏(1)

    Qt 学习之路 2(31):贪吃蛇游戏(1) 豆子 2012年12月18日 Qt 学习之路 2 41条评论 经过前面一段时间的学习,我们已经了解到有关 Qt 相当多的知识.现在,我们将把前面所讲过的知 ...

  6. H5实现的可自定义贪吃蛇游戏

    原创游戏,使用lufylegend.js开发 用canvas实现的贪吃蛇游戏,与一般的贪吃蛇游戏不同,图片经过美工设计,代码设计支持扩展和自定义. 游戏元素丰富,包括障碍物(仙人掌),金币(奖励),苹 ...

  7. Qt 学习之路 2(32):贪吃蛇游戏(2)

    Qt 学习之路 2(32):贪吃蛇游戏(2) 豆子 2012年12月27日 Qt 学习之路 2 55条评论 下面我们继续上一章的内容.在上一章中,我们已经完成了地图的设计,当然是相当简单的.在我们的游 ...

  8. 【C语言项目】贪吃蛇游戏(上)

    目录 00. 目录 01. 开发背景 02. 功能介绍 03. 欢迎界面设计 3.1 常用终端控制函数 3.2 设置文本颜色函数 3.3 设置光标位置函数 3.4 绘制字符画(蛇) 3.5 欢迎界面函 ...

  9. Android快乐贪吃蛇游戏实战项目开发教程-01项目概述与目录

    一.项目简介 贪吃蛇是一个很经典的游戏,也很适合用来学习.本教程将和大家一起做一个Android版的贪吃蛇游戏. 我已经将做好的案例上传到了应用宝,无病毒.无广告,大家可以放心下载下来把玩一下.应用宝 ...

随机推荐

  1. UVA 10334 Ray Through Glasses

    自己手动画了第三项发现f[3]=5;就猜斐波那契了.实际上光线分为两种距离外界有2面玻璃,1面玻璃 其分别时n-1次反射,n-2次反射形成的 故推出斐波那契. 手动一些f1,f2,f3就OK #inc ...

  2. python每日一类(5):itertools模块

    itertools模块包含创建有效迭代器的函数,可以用各种方式对数据进行循环操作,此模块中的所有函数返回的迭代器都可以与for循环语句以及其他包含迭代器(如生成器和生成器表达式)的函数联合使用. ch ...

  3. HDU 17新生赛 身份证验证【模拟】

    身份证验证 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submi ...

  4. POJ 1298 The Hardest Problem Ever【字符串】

    Julius Caesar lived in a time of danger and intrigue. The hardest situation Caesar ever faced was ke ...

  5. java标识符与命名规则

    标识符就是给变量.类或方法起的名字.可以用字母.下划线或美元符号开头,区分大小写,没有最大长度限制.(关键字除外) 关键字   访问控制 private protected public       ...

  6. Python的程序结构[1] -> 方法/Method[0] -> 类实例方法、私有方法和抽象方法

    类实例方法.私有方法和抽象方法 Python中最常用的就是类实例方法,类似于属性中的类实例属性,同时,也存在与私有属性类似方法,即私有方法,下面介绍这两种常见的方法,以及一种特殊意义的类实例方法 -- ...

  7. 代码编辑器[0] -> Vim/gVim[0] -> 基于 Python 的 gVim 环境配置(Windows)

     环境配置 / Environment Setup 基于Python开发的 gVim 环境配置(Windows) 使用方式参考 Vim 的使用. 1 基于vundle进行配置 Vim有多个扩展管理器, ...

  8. hiho一下第129周 后缀自动机二·重复旋律6

    后缀自动机三·重复旋律6 时间限制:15000ms 单点时限:3000ms 内存限制:512MB 描述 小Hi平时的一大兴趣爱好就是演奏钢琴.我们知道一个音乐旋律被表示为一段数构成的数列. 现在小Hi ...

  9. 洛谷 U19159 采摘毒瘤

    题目背景 Salamander见到路边有如此多的毒瘤,于是见猎心喜,从家里拿来了一个大袋子,准备将一些毒瘤带回家. 题目描述 路边共有nn 种不同的毒瘤,第i 种毒瘤有k_i 个,每个需要占据d_i  ...

  10. 分金币 Uva 11300

    题意 给定N个人成环状坐,每个人初始分配Ai的金币,金币总数可以被N整除,每个人可以给左右相邻的人一定数量的金币使得最终每个人的金币数量相同,求转移数量最小的方案所转移的总金币数量. N<=10 ...