`
aaqxhaa
  • 浏览: 5094 次
  • 性别: Icon_minigender_1
文章分类
社区版块
存档分类
最新评论

从零开始制作2048游戏

阅读更多
这次我为大家分享使用Lae软件开发平台制作游戏“2048”的全过程,该游戏的界面UI部分基于lae开发平台开发,业务逻辑和功能实现使用Lae软件开发平台自带的LuaIDE编辑器编写,仅用lua代码300行即可完全实现游戏“2048”的全部功能。(敬请关注Lae软件开发平台官方QQ:176779580)


游戏代码下载地址:https://github.com/ouloba/Game2048.git

游戏代码下载地址(国内):https://pan.baidu.com/s/1o8COrqy

lae下载地址:https://github.com/ouloba/laetool.git

lae下载地址(国内):https://pan.baidu.com/s/1ckMy0Q

1、iPhone上截2048的图

2、用lae参考图功能,打开该图片



3、编辑数字块,不同的数字、不同的颜色



4、编辑游戏界面顶部



5、编辑游戏主窗口,每个格子命名:列x行,主要是通过名字寻找相应的格子坐标用来放置数字格子



6、编辑game over界面



7、在主游戏界面上加个透明按钮(仅有文字)



8、在这详细介召如何制作上面用的窗口,包括点击开始按钮[click to start]、数字方块[number 2048]

<1>编辑[click to start]的创建、布局,渲染,事件处理。

在root窗口上点击右键菜单[add child]添加新的窗口, 设置窗口大小和root窗口一样大小,中间再加入一个窗口title来显示“click to start”文字





title窗口只是为了显示文字不接收事件,因此设置disable为true让父窗口start处理事件



父窗口start处理了点击事件,点击触[OnLClickDown]发时转换成全局事件[OnStart],然后在root窗口上LuaLogic组件处理事件。





在LuaLogic组件中,关联了main.lua文件和main_dispacher事件处理派发接口





<2>数字方块的创建、编辑、渲染

比如number 2048包含back用于显示背景圆角方块和颜色,number用于显示数字.

back主要是Frame用9宫格的方式渲染圆角图片,number只有EditBox组件,整个number 2048窗口设置disable为true,只是用于显示,不处理事件。





<3>

LXZDoFile("LXZHelper.lua");
LXZDoFile("serial.lua");

--记录分数文件
local cfg = ILXZCoreCfg:new_local();
cfg:load(LXZAPIGetWritePath().."game_info.cfg");

local function create_number(name,number)
local root = HelperGetRoot();
local grids = root:GetLXZWindow("game:back grids")
local main = root:GetLXZWindow("game:main");
local dictions = root:GetLXZWindow("dictions")

local pt = grids:GetChild(name):GetHotPos(true); --获取背景格坐标
local w=dictions:GetChild("number "..number):Clone();--从字典中克隆数字窗口
w:SetName(name);                                                   --名字改成和背景格一致
main:AddChild(w);                                                             --加入面板容器窗口
w:SetHotPos(pt,true);                                               --位置和背景格保持一致
w:SetAddData(number);                                                   --指定是数字
AddWndUpdateFunc(w, EffectEase,{type=tween.CIRC, fn=tween.easeOut, begin=0, offset=-0.5, change=0.5, duration=500,reset=true,attribute="CLXZWindow:Scale:fScaleX"},nil, 1);
AddWndUpdateFunc(w, EffectEase,{type=tween.CIRC, fn=tween.easeOut, begin=0, offset=-0.5, change=0.5, duration=500,reset=true,attribute="CLXZWindow:Scale:fScaleY"},nil, 2);
end

--随机出2、4
local function random_number()
local root = HelperGetRoot();
local grids = root:GetLXZWindow("game:back grids")
local main = root:GetLXZWindow("game:main");
local dictions = root:GetLXZWindow("dictions")

--获取空位置
        local tiles = {};
for col=1,4,1 do
for row=1,4,1 do
local number=main:GetChild(col.."x"..row);
if number == nil then
table.insert(tiles, col.."x"..row);
end
end
end

--随机一个空位
local index = math.random(1,table.getn(tiles));
if tiles[index]==nil then
return;
end

--80%的概率出2, 20%的概率出4
local number = 2;
local random = math.random(1,100);
if random>80 then
number=4;
end

--test

--克隆一个数字窗口,加到面板中,位置和背景格重叠
create_number(tiles[index],number);
end

--游戏开始初始化,随机出两个数
local function game_init()
--清除
local root = HelperGetRoot();
local main = root:GetLXZWindow("game:main");
main:ClearChilds();

--
root:GetLXZWindow("start"):Hide();
root:GetLXZWindow("game over"):Hide();


--随机数字
    random_number();
random_number();
--[[create_number("1x1",2);
create_number("2x1",2);
create_number("3x1",2);
create_number("4x1",2);--]]

local bonus_w = root:GetLXZWindow("head:bonus:number");
HelperSetWindowText(bonus_w, tostring(0));
HelperSetWindowText(root:GetLXZWindow("game over:bonus:bonus"), tostring(0));

local maxcore=cfg:GetInt("maxcore");
HelperSetWindowText(root:GetLXZWindow("head:history:number"), tostring(maxcore));


end


local function merge(dst_col, dst_row, src_col, src_row)
local root   = HelperGetRoot();
local main = root:GetLXZWindow("game:main");
local grids = root:GetLXZWindow("game:back grids")
local dictions = root:GetLXZWindow("dictions")

local src = main:GetChild(src_col.."x"..src_row);
if src==nil then
return false;
end

local dst = main:GetChild(dst_col.."x"..dst_row);
if dst == nil then --目标位置为空
local pt = grids:GetChild(dst_col.."x"..dst_row):GetHotPos(true);
src:SetName(dst_col.."x"..dst_row); --reset name.
src:SetHotPos(pt, true); --reset position
return false;
end

--数字不同
if src:GetAddData() ~= dst:GetAddData() then
return false;
end

--相同数字则翻倍,
local number = src:GetAddData()*2;
src:Delete(); --删除原数字
dst:Delete(); --删除目标数字

--克隆新数字
local clone = dictions:GetChild("number "..number):Clone();
main:AddChild(clone);

--放置目标格子位置
local pt = grids:GetChild(dst_col.."x"..dst_row):GetHotPos(true); --获得位置
clone:SetName(dst_col.."x"..dst_row); --reset name.
clone:SetHotPos(pt, true); --reset position
clone:SetAddData(number); --set number
AddWndUpdateFunc(clone, EffectEase,{type=tween.CIRC, fn=tween.easeOut, begin=0, offset=-0.5, change=0.5, duration=500,reset=true,attribute="CLXZWindow:Scale:fScaleX"},nil, 1);
AddWndUpdateFunc(clone, EffectEase,{type=tween.CIRC, fn=tween.easeOut, begin=0, offset=-0.5, change=0.5, duration=500,reset=true,attribute="CLXZWindow:Scale:fScaleY"},nil, 2);
AddWndUpdateFunc(clone, EffectEase,{type=tween.CIRC, fn=tween.easeOut, begin=0, offset=-200, change=200, duration=500,reset=true,attribute="CLXZWindow:Mask:alpha"},nil, 3);

--分数
local bonus_w = root:GetLXZWindow("head:bonus:number");
local bonus = tonumber(HelperGetWindowText(bonus_w));
bonus = bonus+number;
HelperSetWindowText(bonus_w, tostring(bonus));
HelperSetWindowText(root:GetLXZWindow("game over:bonus:bonus"), tostring(bonus));

local maxcore=cfg:GetInt("maxcore");
if bonus>maxcore then
cfg:SetInt("maxcore", -1, bonus);
end

return true;
end

local function tighten_move_line(v,direction)
local root = HelperGetRoot();
local main = root:GetLXZWindow("game:main");
local grids = root:GetLXZWindow("game:back grids")

local count=0;
if direction=="left" then
for col=1,4,1 do
local w = main:GetChild(col.."x"..v);
if w then
count=count+1;
local pt = grids:GetChild(count.."x"..v):GetHotPos(true);
w:SetName(count.."x"..v); --reset name.
w:SetHotPos(pt, true); --reset position
end
end
elseif direction=="right" then
for col=4,1,-1 do
local w = main:GetChild(col.."x"..v);
if w then
local pt = grids:GetChild((4-count).."x"..v):GetHotPos(true);
w:SetName((4-count).."x"..v); --reset name.
w:SetHotPos(pt, true); --reset position
count=count+1;
end
end
elseif direction=="top" then
for row=1,4,1 do
local w = main:GetChild(v.."x"..row);
if w then
count=count+1;
local pt = grids:GetChild(v.."x"..count):GetHotPos(true);
w:SetName(v.."x"..count); --reset name.
w:SetHotPos(pt, true); --reset position
end
end
elseif direction=="bottom" then
for row=4,1,-1 do
local w = main:GetChild(v.."x"..row);
if w then
local pt = grids:GetChild(v.."x"..(4-count)):GetHotPos(true);
w:SetName(v.."x"..(4-count)); --reset name.
w:SetHotPos(pt, true); --reset position
count=count+1;
end
end
end
end

--滑动融合
local function move(direction)
LXZAPI_OutputDebugStr("move:"..direction);

if direction=="top" then
for col=1,4,1 do
tighten_move_line(col, direction);
for row=1,4,1 do
if merge(col, row, col, row+1) then
tighten_move_line(col, direction);
end
end
end
elseif direction=="bottom" then
for col=1,4,1 do
tighten_move_line(col, direction);
for row=4,1,-1 do
if merge(col, row, col, row-1) then
tighten_move_line(col, direction);
end
end
--tighten_move_line(col, direction);
end
elseif direction=="left" then
for row=1,4,1 do
tighten_move_line(row, direction);
for col=1,4,1 do
if merge(col, row, col+1, row) then
tighten_move_line(row, direction);
end
end
--tighten_move_line(row, direction);
end
elseif direction=="right" then
for row=1,4,1 do
tighten_move_line(row, direction);
for col=4,1,-1 do
if merge(col, row, col-1, row) then
tighten_move_line(row, direction);
end
end
--tighten_move_line(row, direction);
end
end
      
random_number();
end

--是否相同
local function is_equal(dst_col, dst_row, src_col, src_row)
local root   = HelperGetRoot();
local main = root:GetLXZWindow("game:main");

local src = main:GetChild(src_col.."x"..src_row);
if src==nil then
return false;
end

local dst = main:GetChild(dst_col.."x"..dst_row);
if dst == nil then --目标位置为空
return false;
end

--数字不同
if src:GetAddData() ~= dst:GetAddData() then
return false;
end

return true;
end

--是否结束
local function is_game_over()
local root   = HelperGetRoot();
local main = root:GetLXZWindow("game:main");
for col=1,4,1 do
for row=1,4,1 do
--如果有空格,则未结束。
local w = main:GetChild(col.."x"..row);
if w== nil then
return false;
end

--到达最大值,则结束
if w:GetAddData()==2048 then
return true;
end

--如果相邻有同值,则未结束。
if is_equal(col,row,col,row+1) then
return false;
end

if is_equal(col,row,col+1,row) then
return false;
end
end
end

return true;
end

local function OnStart(window, msg, sender)
game_init();
end

local function OnUpdate(window, msg, sender)
UpdateWindow();
--LXZAPI_OutputDebugStr("OnUpdate")
end

IsLClickDown= false;
local function OnMainClickDown(window, msg, sender)
IsLClickDown=true;
end

local function OnMainMouseMove(window, msg, sender)
local corecfg = ICGuiGetLXZCoreCfg();
if IsLClickDown==false then
return;
end

local x = msg:int ();
local y = msg:int ();

local origin_x = corecfg.nClickDownX;
local origin_y = corecfg.nClickDownY;

--计算偏移量
local delta_x=x-origin_x;
local delta_y=y-origin_y;

--识别滑动方向
if math.abs(delta_x)>math.abs(delta_y) then
if math.abs(delta_x)>=8 then
if delta_x<0 then
move("left");
IsLClickDown= false;
else
move("right");
IsLClickDown= false;
end
end
else
if math.abs(delta_y)>=8 then
if delta_y<0 then
move("top");
IsLClickDown= false;
else
move("bottom");
IsLClickDown= false;
end
end
end

if is_game_over() then
local root = HelperGetRoot();
root:GetLXZWindow("game over"):Show();
if cfg then
cfg:save(LXZAPIGetWritePath().."game_info.cfg");
end
end

end

--加载完成触发事件
local function OnLoad(window, msg, sender)
local root=HelperGetRoot();
root:GetLXZWindow("game over"):Hide();
root:GetLXZWindow("start"):Show();

local maxcore=cfg:GetInt("maxcore");
HelperSetWindowText(root:GetLXZWindow("head:history:number"), tostring(maxcore));
end

--事件绑定
local event_callback = {}
event_callback ["OnStart"] = OnStart;
event_callback ["OnLoad"] = OnLoad;
event_callback ["OnUpdate"] = OnUpdate;
event_callback ["OnMainMouseMove"] = OnMainMouseMove;
event_callback ["OnMainClickDown"] = OnMainClickDown;

--消息派发接口
function main_dispacher(window, cmd, msg, sender)
--- LXZAPI_OutputDebugStr("cmd 1:"..cmd);
if(event_callback[cmd] ~= nil) then
-- LXZAPI_OutputDebugStr("cmd 2:"..cmd);
event_callback[cmd](window, msg, sender);
end
end
  • 大小: 84.9 KB
  • 大小: 106.2 KB
  • 大小: 95.5 KB
  • 大小: 98.2 KB
  • 大小: 76.3 KB
  • 大小: 94.3 KB
  • 大小: 69.4 KB
  • 大小: 116 KB
  • 大小: 96.5 KB
  • 大小: 143.3 KB
  • 大小: 146.4 KB
  • 大小: 176.7 KB
  • 大小: 35.6 KB
  • 大小: 17.6 KB
  • 大小: 12.5 KB
分享到:
评论

相关推荐

    从零开始学虚幻4游戏开发系列

    ### 从零开始学虚幻4游戏开发系列 #### 虚幻4引擎入门与应用场景 虚幻4引擎是一款强大的游戏开发工具,以其卓越的图形渲染能力、丰富的功能集及直观的操作界面闻名于世。本系列教程旨在为游戏开发新手提供全面的...

    从零开始OPhone游戏编程

    从零开始OPhone游戏编程:全面解析与实践指南 标题与描述强调了“从零开始OPhone游戏编程”,这标志着本文旨在为初学者提供一份详尽的OPhone游戏开发入门指南。OPhone作为一款基于Linux的移动操作系统,针对移动...

    从零开始android游戏编程

    "从零开始Android游戏编程"教程旨在引导那些对游戏开发感兴趣但又无从下手的人们,逐步掌握游戏开发的基本技能。这篇教程从最基础的环境配置开始,确保初学者能够轻松上手。 一、环境配置 1. 安装Java Development ...

    UE4从零开始制作战斗机 的资源

    在本资源包中,我们将深入探讨使用Unreal Engine 4(简称UE4)从零开始制作一架战斗机的全过程。UE4是一款强大的实时渲染引擎,广泛应用于游戏开发、虚拟现实、影视特效等领域。通过这个教程,你将学习到如何利用UE4...

    从零开始学虚幻4游戏开发系列021

    【虚幻4游戏开发系列教程】从零开始学习 虚幻4引擎是当前游戏开发领域广泛应用的一款强大游戏引擎,尤其适合新手入门,因为其引入了蓝图可视化编程系统,使得游戏开发过程无需编写复杂的代码,只需通过图形化界面...

    1.从零开始做游戏-Lua语言基础-1

    【教程】:从零开始做游戏 - Lua语言基础 Lua是一种轻量级的脚本语言,广泛应用于游戏开发,特别是Egame平台的游戏制作。作为初学者,了解并掌握Lua语言的基础是构建游戏逻辑的关键步骤。以下是一份详尽的Lua语言...

    从零开始教你写游戏策划案

    从零开始撰写游戏策划案,首先需要明确目标和定位,根据个人兴趣和熟悉的游戏类型选择切入点。以下是编写游戏策划案的详细步骤和注意事项: 1. **游戏提案(High Concept)**: - 游戏提案是策划案的基础,其目的...

    从零开始OPhone游戏编程ophone8

    《从零开始OPhone游戏编程ophone8》是一本旨在引导初学者入门OPhone游戏开发的教程。OPhone,作为基于Linux的移动操作系统,为开发者提供了丰富的API和开发工具,使得在移动设备上创建应用程序和游戏变得更为便捷。...

    从零开始学习Flash AS3游戏开发.PDF

    ### 从零开始学习Flash AS3游戏开发 #### 核心知识点概览 1. **基础知识准备**:了解Adobe Flash及其ActionScript 3.0 (AS3)编程环境。 2. **开发工具介绍**:使用FlashDevelop进行项目构建与管理。 3. **核心概念...

    Python3.5从零开始学

    作为Python编程入门的资源,本节内容旨在帮助初学者从零开始学习Python3.5,打造扎实的基础,并逐步提升至能够独立编写简单程序的水平。 知识点一:Python语言概述 Python是一种高级编程语言,它强调代码的可读性和...

    手把手教你用C#制作RPG游戏__罗培羽著

    这本书详细介绍了从零开始构建RPG游戏的全过程,涵盖了C#的基础知识以及游戏开发中的各种技术和策略。 在C#语言部分,作者会讲解基本语法、类和对象的概念,以及如何使用面向对象编程来设计游戏结构。C#是微软开发...

    从零开始学编程

    【标题】"从零开始学编程"是一套全面的学习资源,旨在帮助初学者逐步掌握编程技术,特别是针对软件开发和游戏编程领域。这套资源包含了多种编程语言和平台的应用,尤其聚焦于安卓应用开发和游戏制作。 【描述】的...

    android从零开始

    《Android游戏编程之从零开始》是一本专为初学者设计的Android开发指南,适合没有任何Java或Android基础的读者。本书旨在带领读者逐步踏入Android应用和游戏开发的世界,通过实践和理论相结合的方式,掌握Android...

    手把手教你用C#制作RPG游戏

    通过《手把手教你用C#制作RPG游戏》,读者将学习到如何运用C#语言和Unity引擎,从零开始构建一个完整的RPG游戏。这本书的内容涵盖游戏开发的各个层面,无论是对于初学者还是有一定经验的开发者,都能从中受益。

    使用html+css+js+jq制作一个2048的小游戏

    在制作2048游戏时,我们需要创建一个网格布局来放置数字方块。这可以通过使用`&lt;div&gt;`元素和CSS的`display: grid`属性来实现。游戏面板通常会是一个16x16的格子,每个格子由一个`&lt;div&gt;`元素表示。 接下来,CSS...

    掌握UE5:从零开始构建你的游戏项目

    在游戏开发的世界中,Unreal Engine 5(简称UE5)以其...接下来,你可以开始探索更高级的功能,如材质编辑、动画制作、物理模拟等,逐步构建你的游戏世界。UE5的强大功能和灵活性,将为你的游戏开发之旅提供无限可能

Global site tag (gtag.js) - Google Analytics