手机自动出现2048小游戏做屏保,电脑屏保怎么取消消

2048游戏(自己做2048)_百度知道
2048游戏(自己做2048)
有个网站似乎是可以自己做2048……但是要怎么插图片啊?似乎只能改字的样子
我有更好的答案
自定义网站~~~
采纳率:26%
求问是哪个网站啊???
df dsf dsg
1条折叠回答
为您推荐:
其他类似问题
2048的相关知识
换一换
回答问题,赢新手礼包
个人、企业类
违法有害信息,请在下方选择后提交
色情、暴力
我们会通过消息、邮箱等方式尽快将举报结果通知您。2048(小游戏) 是一款比较流行的数字游戏,最早于日发行。 原版2048首先在GitHub上发布,原作者…阅读全文关注话题分享阅读全文1.7K222 条评论分享收藏感谢阅读全文1.2K215 条评论分享收藏感谢阅读全文750131 条评论分享收藏感谢阅读全文9260 条评论分享收藏感谢阅读全文7568 条评论分享收藏感谢619他的最新文章
他的热门文章
您举报文章:
举报原因:
原文地址:
原因补充:
(最多只允许输入30个字)博客分类:
&&&&&&&&&&&&&&&&&&&&&&&&& 2048小游戏总结
1.什么是2048
&&&&& 2048就是一款在九宫格内通过操控上下左右这四个键,每当遇到两个相同的数字叠到一起时候,我们就会按下与它叠的方向相同的两个方向的按键,促使他们相加在一起变成一个他们
相加的数字,当在九宫格内出现2048时,则游戏胜利;但九宫格内的九个格子都被填满了数字,并且在任何方向上都没有叠在一起的相同数字时,则游戏失败。这个游戏在小游戏中属于比较
经典的益智小游戏。
2.2048游戏项目的开发经历
&&&&& 起初当听到要做这个游戏的时候有点蒙,因为没有玩过这一类型的游戏,所以对于他的实现感到非常的迷茫,有一种“敢问路在何方”的感觉!后来通过队友们的介绍与自己的体验终
于看到一前方100米的路程。抱着种船到桥头自然直的想法,就开始了自己的2048游戏开发项目,项目开发过程:画出游戏界面→在界面中随机出现2或4的两张数字图片→图片每移动一次都会
在随机位置随机一张2或4的一张图片→将两个相连的相同数字的图片相加→ 最后出现2048为赢,出现不能随机出现新的图片时为失败。
3.开发中所遇到的问题及解决
&&&&& 每一个开发的项目都会遇到许多的问题,特别是对于我们这种新手来说,但是我们不拍,我们要有遇山开山,遇河搭桥的精神。
&&& 界面中图片的绘制都是利用二维数组存值得方式来实现。
&&&&& (1)问题:将所有图片移动你按键的方向到问题
&&&&&&&&&&& 我的解决方法是你往什么方向按方向键,就从你按键的方向作为第一个一行一行或者一列一列的遍历,有扫到的第一个图片的与遍历的起始位置交换数组的数据,第二个图片就
与第二个交换位置,以此类推下去就能做到图片都往一个方向的移动。
&&&&&& (2)问题:按方向键后相连的相同图片相加的问题
&&&&&&&&&&&& 跟上面遍历的方法差不多,当遍历到有相同数组中的值有相同的值时,就会画出他们相加的值的图片,数组中的值也要发生相应的改变。
&&&&&& (3)问题:就是每次按下方向键会要随机出现一张2或者4的图片,此图片会对已有的图片的位置进行覆盖的问题
&&&&&&&&&&&&& 此问题是利用递归的方法来判断你随机的位置上是否已有图片,如若有侧继续随机,如果没有则在此位置画出图片。
4.游戏开发后的感想
&&&&& 起初做这个2048的时候,没有太多的自信,总认为这个比较难不太好做,在开发的过程中遇到无法解决问题的问题的时候也会比较烦。有时也会有想放弃的时候,但是最后还是坚持过
来了,做出后自己也很有成就感。
&&&&& 从这上面我自己感悟到,其实有很多东西我们都是能做到的,只是我们还不了解现在的自己,对自己的认识还是停留在以前。只要我们敢做就一定能做到,这是我做这个游戏后领悟出
的道理,同时对于自己解决问题的能力也有了明显的提高。
浏览: 1975 次
(window.slotbydup=window.slotbydup || []).push({
id: '4773203',
container: s,
size: '200,200',
display: 'inlay-fix'4663人阅读
个人项目总结(1)
本文乃Siliphen原创,转载请注明出处:
最近开始学习unity。学习最好的方法是动手实践。
因为游戏2048画面简单,可以自己搞定,于是选择2048作为练手对象。
在动手练习的过程中,自己积累了实践经验,也加深了对unity的理解。
写下此文,作为学习总结。希望和大家交流,彼此促进进步。
我的2048游戏可执行文件在本文的末尾可以下载到。
做出来的效果如下:
2048是一个益智游戏。规则是:
在 4&× 4 大小的棋盘上,玩家可以选择向“上,下,左,右”四个方向滑动方块,每次滑动成功,所有方块向滑动的方向靠拢。
相邻的且数字相同的方块会合并成一个新的方块,这个方块的数字是原先2个方块的和。
每次滑动成功,或合并成功,都会在棋盘空白区域随机位置生成一个数字是2或4的新方块。
游戏初始时,棋盘上会出现2个方块。
输的条件:棋盘填满方块,且没有方块能够合并成新的方块。
赢的条件:棋盘上出现数字为2048的方块。
游戏玩法示意图如下:
玩法细节:方块的结合律
在动手实现游戏之前,需要把核心玩法的细节都确定好。
方块水平序列( 2 2 2 )向左滑动的结合结果是:(4 2)
方块水平序列(&2 2 2 )向右滑动的结合结果是:(2 4)
方块优先向滑动的方向结合。
方块水平序列 (2 2 2 2) 向左、向右滑动的结合结果是:(4 4)
每次滑动方块,方块之间只能结合一次。
若要使上述情况结合成8,需要滑动2次。
垂直序列以此类推。
核心玩法类图
资源文件组织
清晰的、有规律的文件组织,能够提高开发效率,降低维护成本。
“scenes”文件夹用于放置unity的场景文件。如下图:
“scripts”文件夹用于放置脚本文件。
“scripts/scenes”文件夹以场景为单位来分类代码,每个场景文件夹下有3个文件夹,分别是:
“controller”,放置控制器代码。
“model” , 放置模型代码。
“view”,放置和用户UI界面有关的代码。
代码分类结构如下图:
其中,game_play 表示核心玩法场景。home 表示首页场景。
场景代码入口函数
很多语言和框架,都有一个程序入口函数,例如C,C#的main,
而 Unity 并没有类似这样一个所谓的“代码入口”,代码都是作为组建挂载到 GameObject 上才能执行。
为了清晰,本项目每个场景都设置一个入口脚本,这个脚本是这个场景运行的第一个脚本,其他脚本通过这个脚本进行初始化和挂载。
核心玩法的入口脚本:
using UnityE
using System.C
public class SceneEntryGameplay : MonoBehaviour
// Use this for initialization
void Start ()
// 加上其他的脚本
gameObject.AddComponent&CtrlGameplay&();
gameObject.AddComponent&UserInput&();
// Update is called once per frame
void Update ()
这个入口脚本挂载到场景中的一个叫“Entry”的空GameObject上,
节点 Entry&和脚本&SceneEntryGameplay&就是这个场景所有代码来龙去脉的起点。
因为做的游戏是2D的,所以,创建项目时,选择2D项目。
摄像机属性【Projection】选择【 orthographic】,【size】设置为“6.4”。如下图所示:
为什么【size】是6.4呢。这个是通过适配分辨率算出来的,
假设要做的游戏的分辨率是 720 * 1280 ,那么 size = &6.4 =&720 / 2 / 100 ,
unity会在任何分辨率的手机上,锁定高度,扩展宽度。
几乎所有的2D游戏的分辨率适配都是通过设置摄像机的size。
核心玩法之基础搭建
获取用户输入
在unity中接收PC鼠标的输入和接收手机触摸的输入,分别用不同的方法。
为了调试方便,我们要同时支持PC和手机的输入。
我们定义:PC的鼠标按下左键 等同于 手机触屏的按下手指。PC的鼠标按下左键滑动 等同于 手机触屏的手指滑动。
脚本“UserInput”用来接收用户的输入。路径:“scripts/scenes/game_play/view/input”
简化的框架代码如下:
using UnityE
using System.C
using UnityEngine.UI;
获取用户输入
public class UserInput : MonoBehaviour
// Use this for initialization
void Start()
// Update is called once per frame
void Update()
// 处理鼠标的输入
void Mouse()
if( Input.GetMouseButtonDown( 0 ) )
m_MouseMove =
else if( Input.GetMouseButtonUp( 0 ) )
m_MouseMove =
if( m_MouseMove == true )
// 处理移动设备的输入
void Touch()
if( Input.touchCount == 0 )
var touch = Input.GetTouch( 0 );
if( touch.phase == TouchPhase.Began )
else if( touch.phase == TouchPhase.Moved )
// 标示鼠标是否是按下的移动
bool m_MouseMove =
UserInput类同时支持PC鼠标和移动设备的输入,其中PC鼠标的输入需要一个变量&m_MouseMove&来标示是否是按下鼠标键的滑动,
按下鼠标左键时,&m_MouseMove = true 。抬起鼠标左键时,&m_MouseMove = false。
通过&m_MouseMove 变量,在按下鼠标左键和抬起左键之间的鼠标运动,都认为是按下左键的滑动,
这样就在PC上用鼠标模拟了移动设备的手指滑动。
UserInput类需要挂载到GameObject上才能运行,
代码入口类“SceneEntryGameplay”负责挂载这个脚本。
手势识别的作用是确定用户的操作意图。
2048的手势规则是:
手指快速向左滑动一段距离,认为是向左滑动的操作。类推向右,上,下。
手指按下后滑动速度超过某个时间长度,操作无效。
滑动操作成功后,不松手再滑动,操作无效。
每次有效滑动操作需要经历:
1.手指按下。2.朝某个方向,在指定时间内,滑动指定长度距离。
在“UserInput”类中,我们已经兼容了PC和手机的操作,
现在需要一个手势识别类,可复用在PC和手机的操作上。
脚本“Direction”用来定义滑动方向。路径:“scripts/scenes/game_play/controller”。
public enum Direction
脚本“CtrlInput”是手势识别类。路径:“scripts/scenes/game_play/view/input”
代码如下:
using UnityE
处理用户输入
public class CtrlInput
public class EventArgsCtrlInput : EventArgs
public Direction Direction { }
public event EventHandler&EventArgsCtrlInput& M
// 开始接收输入
public void Start( Vector3 pt )
        // 记录原点位置
        m_ptStart =
        // 记录触摸开始时间
        m_TimeStart = Time.fixedT
        // 本次操作有效
        m_Flag =
// 检查输入
public void Check( Vector3 pt )
if( m_Flag == false )
if( Time.fixedTime - m_TimeStart & 3 )
// 滑动超时
var v = pt - m_ptS
// 相对于起始点的距离。
var len = v.
if( len & m_Len )
var degree = Mathf.Rad2Deg * Mathf.Atan2( v.x , v.y );
if( -45 &= degree && degree &= -135 )
Move( this , new EventArgsCtrlInput() { Direction = Direction.Left } );
else if( 45 &= degree && degree &= 135 )
Move( this , new EventArgsCtrlInput() { Direction = Direction.Right } );
else if( -45 &= degree && degree &= 45 )
Move( this , new EventArgsCtrlInput() { Direction = Direction.Up } );
else if( 135 &= degree || degree &= 135 )
Move( this , new EventArgsCtrlInput() { Direction = Direction.Down } );
// 触摸起点
Vector3 m_ptS
// 滑动的有效长度
int m_Len = 30;
// 时间起点
float m_TimeS
    // 用于控制操作识别完成后,不松手再滑动,操作无效。
    bool m_Flag =
class CtrlInput 识别出手势后会发出“Move”事件。
手势识别的原理是,逻辑上,以原点为中心把滑动空间分成4部分,上,下,左,右,每个部分90度,判断用户手指滑动的方向。
示意图如下:
Start 函数在手指按下时调用,用来定位原点在屏幕上的位置,也就是初始化原点。
Check 函数用来检查手指移动到的点是否符合手势条件,做滑动方向判断。
通过原点和手指滑动到的点算出来的角度来确定用户是往哪个方向滑动。
例如:(45)到(-45)这个范围表示向上滑动。以此类推左,右,下方向。
class CtrlInput需要被 class&UserInput 调用,
class UserInput 实际代码如下:
using UnityE
using UnityEngine.UI;
获取用户输入
public class UserInput : MonoBehaviour
// Use this for initialization
void Start()
m_Text = GameObject.Find( &txtInfo& ).GetComponent& Text &();
m_CtrlGameplay = GetComponent& CtrlGameplay &();
m_CtrlInput.Move += OnM
// Update is called once per frame
void Update()
// 处理鼠标的输入
void Mouse()
if( Input.GetMouseButtonDown( 0 ) )
m_MouseMove =
m_CtrlInput.Start( Input.mousePosition );
else if( Input.GetMouseButtonUp( 0 ) )
m_MouseMove =
if( m_MouseMove == true )
m_CtrlInput.Check( Input.mousePosition );
// 处理移动设备的输入
void Touch()
if( Input.touchCount == 0 )
var touch = Input.GetTouch( 0 );
if( touch.phase == TouchPhase.Began )
m_CtrlInput.Start( touch.position );
else if( touch.phase == TouchPhase.Moved )
m_CtrlInput.Check( touch.position );
void OnMove( object sender , CtrlInput.EventArgsCtrlInput e )
// 在UI上显示移动方向
m_Text.text = e.Direction.ToString();
// 主控制器尝试用户的合并操作。
m_CtrlGameplay.Merge( e.Direction );
// 标示鼠标是否是按下的移动
bool m_MouseMove =
// 处理输入
CtrlInput m_CtrlInput = new CtrlInput();
// 核心玩法主控制器
CtrlGameplay m_CtrlG
// 用于调试信息显示的文本控件
public UnityEngine.UI.Text m_Text =
class UserInput的事件处理器&OnMove 用来响应处理合法的用户手势操作,
这里会给游戏逻辑控制器 CtrlGameplay 发送控制指令。
游戏是在 4 * 4 的矩阵中进行。可以用二维数组&List& List& Cell & & 来表示棋盘的逻辑结构。
其中Cell表示的是棋盘的每个单元格。
这里,我们直接用GameObject来定位棋盘的每个单元格。
在 Hierarchy 面板中创建一个叫“Map”的GameObject作为地图的根节点,
在“Map”下建立 4 * 4 = 16 个GameObject作为地图的每个单元格,单元格GameObject的命名规则是:“tile_行索引_列索引”。
如下图所示:
棋盘的背景可以自己发挥,这里是直接帖了一张图。
脚本“Map”用于表示整个棋盘。路径:“scripts/scenes/game_play/model”
代码如下:
using UnityE
using System.C
using System.Collections.G
public class Map
List&List&Cell&& m_C
static readonly Map m_Ins = new Map();
public static Map Instance
return m_I
// 初始化。解析场景,生成棋盘地图逻辑结构。
public void Init()
m_Cells = new List&List&Cell&&();
for( int i = 0 ; i & 4 ; ++i )
var row = new List&Cell&();
m_Cells.Add( row );
for( int x = 0 ; x & 4 ; ++x )
row.Add( new Cell() );
for( int y = 0 ; y & 4 ; ++y )
for( int x = 0 ; x & 4 ; ++x )
var name = string.Format( &tile_{0}_{1}& , y , x );
var tile = GameObject.Find( name );
var theCell = m_Cells[ y ][ x ];
theCell.Position = tile.transform.
theCell.Coord = new Vector3( x , y , 0 );
public List&List&Cell&& Cells
return m_C
public class Cell
// 单元格在棋盘中的逻辑坐标。
public Vector3 Coord
// 单元格在世界空间中的坐标。
public Vector3 Position
// 单元格绑定方块实体。
public GameObject Entity
class&Map 的 Init方法解析场景的棋盘数据,生成棋盘地图逻辑结构。
实体&Entity&的定义比较广泛,在游戏中一般表示一个游戏体。
本项目中,游戏实体“Entity”的定义是:在游戏中出现的方块。
方块需要一些属性用来进行计算。比如:方块所代表的分值。
Unity是组件式编程,GameObject基本上就相当于表示游戏实体了。
要为游戏实体增加属性和行为,只能用为GameObject增加脚本组件的方式。
脚本“EntityProperty”用于表示游戏实体属性。路径:“scripts/scenes/game_play/model”
代码如下:
using UnityE
public class EntityProperty : MonoBehaviour
// Use this for initialization
void Start ()
// Update is called once per frame
void Update ()
public int Score
// 关联的单元格
public Cell AssociatedCell
// 是否可以合并
public bool MergeEnabled
路径:“Resources/prefabs/entities”下,创建表示”2,4,8,16,32,64,128,256,512,“分值的几个游戏实体预制,如下图:
为了方便地创建出方块实体,可以写一个方块工厂类,一句话生成方块实体。
“FactoryEntity”游戏实体工厂类。路径:“scripts/scenes/game_play/controller”。
class FactoryEntity
static public GameObject Create( int Score )
var path = &prefabs/entities/entity_& + S
var prefab = Resources.Load( path ) as GameO
var theEntity = GameObject.Instantiate( prefab );
// 设置分值
var theEntityProperty = theEntity.GetComponent&EntityProperty&();
theEntityProperty.Score = S
theEntityProperty.MergeEnabled =
return theE
核心玩法之控制器
到了这里,游戏手势识别,地图,方块实体都已经准备好了。
现在还缺一组控制器用来实现游戏流程的行为控制。
主控制的责任是容纳和管理其他的几个子控制器,做最顶层控制流程管理。
而子控制一般只负责单一控制功能。
主控制和子控制器的关系如下:
脚本“CtrlGameplay”作为游戏核心玩法的主控制器。路径:“scripts\scenes\game_play\controller”。代码如下:
using UnityE
public class CtrlGameplay : MonoBehaviour
public void Merge( Direction dir )
m_CtrlMerge.Merge( dir );
if( m_CtrlMerge.HasMerged == true )
Audio.Instance.Play( &merge& );
if( m_CtrlMerge.HasMoved == true )
Audio.Instance.Play( &move& );
m_State = 1;
// Use this for initialization
void Start ()
// 初始化地图
Map.Instance.Init();
// 初始化实体生成器
m_EntityGenerator.Init();
// 开始游戏时生成的实体
m_EntityGenerator.GenerateFirst();
// 初始化合并控制器
m_CtrlMerge.Finish += OnFinishM
m_CtrlMerge.CreateEntity += Tracker.Instance.OnCreateE
// 初始化UI
UiGameplay.Instance.Init();
UiGameplay.Instance.Refresh();
void Update()
if( m_State == 1 )
m_CtrlMerge.CheckFinish();
// 完成一轮行动
void Finish()
m_State = 0;
m_EntityGenerator.Generate();
var JudgeRet = m_Judgement.Judge();
if( JudgeRet == Judgement.JudgeRet.Lose )
int a = 1;
else if( JudgeRet == Judgement.JudgeRet.Win )
int a = 1;
void OnFinishMerge( object sender , EventArgs e )
if( m_CtrlMerge.HasMoved == true )
#region Private Fields
// 实体生成
EntityGenerator m_EntityGenerator = new EntityGenerator() ;
CtrlMerge m_CtrlMerge = new CtrlMerge();
Judgement m_Judgement = new Judgement();
int m_State = 0;
#endregion
之前说过,核心玩法的场景只有一个入口函数类“SceneEntryGameplay”,这个类负责加载其他的组件代码。
脚本CtrlGameplay也是在SceneEntryGameplay中被挂载上的。
游戏核心玩法主控制器“CtrlGameplay”只有一个公共方法“Merge”。
Merge方法方法由类UserInput调用,当类UserInput检测到玩家输入了一个合法的指令(例如向左滑动)时,就调用该方法。
CtrlGameplay.Merge内部是通过调用子控制器来完成功能。
方块实体生成控制器
类EntityGenerator是方块实体生成控制器。路径:“scripts/scenes/game_play/controller”
它的作用是,移动或者合并完成后,在棋盘空余的地方生成新的方块。
代码如下:
using UnityE
using System.Collections.G
// 实体生成器
public class EntityGenerator
public void Init()
// 游戏初始时的生成逻辑。
public void GenerateFirst()
for( int i = 0 ; i & 2 ; ++i )
Generate();
// 生成实体
public bool Generate()
// 选出空余的位置
List&Cell& EmptyCells = new List&Cell&();
var Cells = Map.Instance.C
for( int y = 0 ; y & Cells.C ++y )
for( int x = 0 ; x & Cells[ y ].C ++x )
if( Cells[ y ][ x ].Entity == null )
EmptyCells.Add( Cells[ y ][ x ] );
if( EmptyCells.Count == 0 )
int idx = Random.Range( 0 , EmptyCells.Count - 1 );
var theCell = EmptyCells[ idx ];
// 生成实体
var entity1 = FactoryEntity.Create( 2 );
entity1.transform.position = theCell.P
theCell.Entity = entity1;
方块实体合并控制器
实体合并控制器只完成一个工作:朝指定方向滑动方向,合并方块。
合并与滑动方块的算法用向左滑动为例来说明:
* 遍历地图的每一行,对于每行从左向右扫描单元格。
* 如果当前扫描到的地图单元格有方块的话,向左查找一个最近的方块。最近的方法的定义是,没有被其他方块阻隔。
* 找到了最近的方块,判断是否可以合并,如果可以合并,就销毁这2个方块,在左边的方块的位置上生成一个新合并后的方块。
* 如果没有找到可以合并的方块,就向左查找一个最左的空的位置,看是否可以移动到空的位置上。
算法图示如下:
向右,向上,向下的算法以此类推。
最终的效果如下所示:
代码有400行之多,这里就不贴了。
方块实体移动控制
cocos2d 对于物体的移动,缩放等有很好的支持,动作 MoveTo 一句话就可以执行运动。
而unity的物体运动,需要自己在Update函数中写代码。
如果是用位置不断加速度的做法,很容易会造成“穿越”目的点,而不是刚好停在目标点上。
这里,模仿cocos2d的Action MoveTo,设计一个移动控制器来控制方块实体的移动。
该控制器需要2个参数:时间长度,目的点。
功能:在指定的时间内达到指定的目的点。
代码如下:
using UnityE
using System.C
public class MoveTo : MonoBehaviour
public EventHandler F
// Use this for initialization
void Start ()
// Update is called once per frame
void Update ()
m_Elapsed += Time.deltaT
var f = m_Elapsed / m_D
if( f &= 1 )
gameObject.transform.position = m_Src + m_v;
if( Finish != null ) Finish( this , null );
var pt = m_Src + m_v *
gameObject.transform.position =
public void Start( float Duration , Vector3 dst )
this.m_Duration = D
this.m_Dst =
m_Src = gameObject.transform.
m_v = dst - m_S
m_Elapsed = 0;
Vector3 m_D
float m_Elapsed = 0;
Vector3 m_S
Vector3 m_v;
MoveTo.Start 函数用于启动运动,启动运动时,记录当前位置,算出当前位置和目标位置的向量。
然后 Update 函数,计算当前流逝的时间和目标时间的百分比,确定在当前时间点,应该朝向目标位置移动多少距离。
使用原位置不断执行偏移量加法的方法,可以避免计算误差,最后精确地落在目标点上。
判断游戏输赢
判定游戏输赢依次执行以下步骤:
* 如果出现了2048数字的方块,判赢。
* 如果棋盘还有空位,游戏继续。
* 如果棋盘没有空位,但有可以合并的方块,游戏继续。
下载本文的游戏demo
本文章的2048游戏demo下载地址(包含 PC ,Android 平台):
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:233156次
积分:2442
积分:2442
排名:第17607名
原创:25篇
评论:362条
(1)(1)(1)(1)(2)(1)(4)(1)(4)(1)(3)(2)(3)

我要回帖

更多关于 小游戏2048 的文章

 

随机推荐