從零開始製作2048遊戲 原 薦

遊戲代碼下載地址: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

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章