Matlab GUI 制作俄罗斯方块小游戏

成品视频播放链接点击此处跳转观看。        

        使用matlab制作俄罗斯方块小游戏,首先考虑到的是使用GUI来完成,GUI可以实现方块的显示、键盘的控制、整体逻辑的实现。本文依照结构框架和实现代码来完成介绍。结构框架可分为初始化、逻辑控制、方块控制、按键控制、美化界面五个部分,每个部分下有着细化的分支流程。

俄罗斯方块框架结构
俄罗斯方块界面总览

1、初始化

        此节作为俄罗斯方块的初始化部分,主要为整个界面的构造以及方块的种类定义。

1.1、方块生成

        在matlab的GUI中为了表示方块,可以使用“静态文本”构件,静态文本可以通过两层循环调整出现位置,我生成了一个19*29的方格矩阵,背景采取灰色。实现代码为:

%俄罗斯方块显示框
for i = 1:Length
    for j = 1:High-1
        
        Block(i,j) = uicontrol(F,'style','text',...
            'position',[(i-1)*Side_length+1,(j-1)*Side_length+5,Side_length*0.95,Side_length*0.95],...
            'userdata',[i,j],'backgroundcolor',Grey_color);
        
    end
end

1.2、颜色控制

        在“静态文本”框中可以切换背景颜色,控制语句为:

Grey_color = [0.8,0.8,0.8];
Bule_color= [0.075,0.624,1.0];

set(handles.text1,'backgroundcolor',Grey_color);
set(handles.text2,'backgroundcolor',Bule_color);

        颜色的数据属性对应的是RGB三色数值。

1.3、方块种类

        在俄罗斯方块中方块种类存在七种,分别为 I、L(左)、L(右)、O、N(左)、N(右)、T,其形状如下图所示:

七种方块构型

         在代码中可以规定每个构型的定位点,然后根据其位置关系推导出其他三个方块的坐标,不同的方块代码如下所示:

%I
length1 = op_length;length2 = op_length;length3 = op_length;length4 = op_length;
high1 = op_high;high2 = op_high-1;high3 = op_high-2;high4 = op_high-3;

%L(左)
length1 = op_length;length2 = op_length;length3 = op_length;length4 = op_length+1;
high1 = op_high;high2 = op_high-1;high3 = op_high-2;high4 = op_high-2;

%L(右)
length1 = op_length;length2 = op_length;length3 = op_length;length4 = op_length-1;
high1 = op_high;high2 = op_high-1;high3 = op_high-2;high4 = op_high-2;

%O
length1 = op_length;length2 = op_length+1;length3 = op_length;length4 = op_length+1;
high1 = op_high;high2 = op_high;high3 = op_high-1;high4 = op_high-1;

%N(左)
length1 = op_length;length2 = op_length;length3 = op_length+1;length4 = op_length+1;
high1 = op_high;high2 = op_high-1;high3 = op_high-1;high4 = op_high-2;

%N(右)
length1 = op_length;length2 = op_length-1;length3 = op_length;length4 = op_length-1;
high1 = op_high;high2 = op_high-1;high3 = op_high-1;high4 = op_high-2;

%T
length1 = op_length;length2 = op_length-1;length3 = op_length+1;length4 = op_length;
high1 = op_high;high2 = op_high;high3 = op_high;high4 = op_high-1;

2、逻辑控制

        此节为方块的逻辑操作部分,包括方块的向下移动、方块的速度叠加、得分情况判断、边界判定以及游戏结束判定。

2.1、方块下移

        方块生成之后,按照一定速度向下移动,直到下降到最底部。其下降的逻辑为:(1)取消当前方块显示;(2)刷新方块下降后的坐标;(3)新增下降后的方块显示;(4)暂停代码运行固定时间。实现代码为:

%%方块往下走
while Bottom_Valid ==0 && Down_Valid ==0

        
        %取消前个方块显示
        [op,Left_Valid,Right_Valid,Bottom_Valid,Down_Valid,Deformation_Valid] = Type_Block(Block,R_Num);
        set(op,'backgroundcolor',Grey_color);
        
        %由于混合按键,Down_Valid数值会发生变化,再次进行判断
        if Down_Valid == 0
            op_high = op_high -1;
        else
            [op,Left_Valid,Right_Valid,Bottom_Valid,Down_Valid,Deformation_Valid] = Type_Block(Block,R_Num);
            set(op,'backgroundcolor',Bule_color);
            continue;
        end
        
        %新增方块显示
        [op,Left_Valid,Right_Valid,Bottom_Valid,Down_Valid,Deformation_Valid] = Type_Block(Block,R_Num);
        set(op,'backgroundcolor',Bule_color);
        
        %添加声音
        Play_Sound(1);%方块下降音效

        pause(Speed);%每隔固定时间下落一格高度
        
        %判断是否可下降
        [op,Left_Valid,Right_Valid,Bottom_Valid,Down_Valid,Deformation_Valid] = Type_Block(Block,R_Num);
        set(op,'backgroundcolor',Bule_color);
        
    end
    
    %传递下一个变形标志位
    R_Num = R_Num_Next;
    
    %添加声音
    Play_Sound(3);%方块触底声音
    
end

2.2、随机生成方块

        每次生成的方块均为七种方块的随机一个,实现代码如下:

R_Num = randi([1,7]);%设置随机方块

function [op,Left_Valid,Right_Valid,Bottom_Valid,Down_Valid,Deformation_Valid] = Type_Block(Block,R_Num)

switch R_Num
    %串联需要注意矩阵维度一致
    case 1
        %I方块
    case 2
        %L方块(左)
    case 3
        %L方块(右)
    case 4
        %O方块
    case 5
        %N方块(左)
    case 6
        %N方块(右)
    case 7
        %T方块
end

end

2.3、方块下降速度随得分发生变化

        为了难度随方块下降速度递增,每得一分后速度增加10%,实现代码如下:

%速度随分数发生变化
if mod(Rec_Score,1) == 0
   if Rec_Score~=Rec_Score_Pre
       Speed_In = Speed_In/1.1;
       Speed = Speed/1.1;
   end
end
Speed  = Speed_In;%内部速度需要赋值

2.4、得分判定

        当方块触底之后,对当前的方块进行判断,如若存在一行方块全为显示的状态,则取消当前行方块,并且计分一次。实现代码如下:

    %检测四次
    for Num = 1:4
        %成功满足一行 消除这一行
        for Row = 1:High-1 %逐行搜索
            
            %检测是否满一行填充为蓝色
            for Col = 1:Length
                if isequal(get(Block(Col,Row),'backgroundcolor'),Bule_color)
                else
                    Col = 1;%出现空白列数置为1
                    break%遇到灰色 跳出循环
                end
            end
            
            Rec_Block = [];
            %代表可以消除此行
            if Col == Length
                
                %记录得分情况
                Rec_Score = Rec_Score+1;
                Play_Sound(5);%方块消除音效
                set(Rec_Score_Block,'string',num2str(Rec_Score));
                
                for delete_Col = 1:Length
                    set(Block(delete_Col,Row),'backgroundcolor',Grey_color);
                end
                
                for Rec_Row = Row+1:High-1
                    for Rec_Col = 1:Length
                        if isequal(get(Block(Rec_Col,Rec_Row),'backgroundcolor'),Bule_color)
                            Rec_Block = [Rec_Block,Block(Rec_Col,Rec_Row-1)];
                            set(Block(Rec_Col,Rec_Row),'backgroundcolor',Grey_color);
                        end
                    end
                end
           
                set(Rec_Block,'backgroundcolor',Bule_color);
            end
        end
    end

2.5、边界判定

        方块移动左、右、下边界时需要停止移动,这里为三个函数实现判定:

%判断是否能够向下运动
function Down_Valid = Down_Judgment(Block,Length_matrix,High_matrix)

global Bule_color;
Down_Valid = 0;

for i = 1:length(Length_matrix)
    if High_matrix(i) ~= 1
        if isequal(get(Block(Length_matrix(i),High_matrix(i)-1),'backgroundcolor'),Bule_color)
            Down_Valid = 1;
        end
    end
end

end
%完成对方块左右运动以及边界的判定
function  Right_Valid= Right_Judgment(Block,Length_matrix,High_matrix)

%输入 Block:                  方块句柄
%        Length_matrix      方块坐标矩阵长度方向
%        High_matrix          方块坐标矩阵高度方向

%输出 Right_Valid    判定值,0表示正常 1代表无法左移动 2代表无法右移动

global Bule_color
Right_Valid = 0;

for i = 1:length(Length_matrix)
    
    
    %判断右运动判定
    if Length_matrix(i) ~=19
        if isequal(get(Block(Length_matrix(i)+1,High_matrix(i)),'backgroundcolor'),Bule_color)
            Right_Valid = 1;
        end
    end
    
    %右边界判定
    if Length_matrix(i) ==19
        Right_Valid = 1;
    end
    
end

end
%完成对方块左右运动以及边界的判定
function  Left_Valid= Left_Judgment(Block,Length_matrix,High_matrix)

%输入 Block:                  方块句柄
%        Length_matrix      方块坐标矩阵长度方向
%        High_matrix          方块坐标矩阵高度方向

%输出 Left_Valid    判定值,0表示正常 1代表无法左移动 2代表无法右移动

global Bule_color
Left_Valid = 0;

for i = 1:length(Length_matrix)
    
    %判断左运动判定
    if Length_matrix(i) ~=1
        if isequal(get(Block(Length_matrix(i)-1,High_matrix(i)),'backgroundcolor'),Bule_color)
            Left_Valid = 1;
        end
    end
    
    %左边界判定
    if Length_matrix(i) ==1
        Left_Valid = 1;
    end
    
end

end

2.6、游戏结束判定

        游戏结束的标志为当方块触底之后,如若存在方块显示在最上边一行,代表游戏已经结束,并且有弹窗和文字提示信息。

%游戏结束判定
    for ii = 1:Length
        if isequal(get(Block(ii,High-1),'backgroundcolor'),Bule_color)
            
            %添加游戏结束音效
            Play_Sound(4);
            flag_stop = 1;
            break;
        end
    end
    
    if flag_stop == 1
        break
    end

3、方块控制

        游戏的关键为使用键盘完成对方块的交互,在matlab的GUI中为设置方块移动以及变形的快捷键。

3.1、左右移动

        键盘"<-"左键、"->"右键为控制方块的左右移动,左右移动的逻辑为使方块的坐标+1、-1,并且将触发函数的按键设置一下。

3.2、变形控制

        方块的变形为方块按照一个方向旋转90°,每种方块有四种旋转后的形态,有些方块的对称性原因,旋转后的形态只有一种(O形)、两种(I形、N形左、N形右)。变形的按键设置为空格。

3.3、向下加速

        当按下键盘的向下箭头时,方块会按照固定速度向下移动。

三种控制的实现代码为:

function Move_Block(hObject,eventdata,Block,R_Num)

Key = eventdata.Key;

switch Key
    
    case 'rightarrow'
        
        [op,Left_Valid,Right_Valid,Bottom_Valid,Down_Valid,Deformation_Valid] = Type_Block(Block,R_Num);
        
        if Right_Valid ~= 1
            set(op,'backgroundcolor',Grey_color);
            
            op_length = op_length+1;
            [op,Left_Valid,Right_Valid,Bottom_Valid,Down_Valid,Deformation_Valid] = Type_Block(Block,R_Num);
            set(op,'backgroundcolor',Bule_color);
        end
        
        
    case 'leftarrow'
        
        [op,Left_Valid,Right_Valid,Bottom_Valid,Down_Valid,Deformation_Valid] = Type_Block(Block,R_Num);
        
        if Left_Valid ~= 1
            set(op,'backgroundcolor',Grey_color);
            
            op_length = op_length-1;
            [op,Left_Valid,Right_Valid,Bottom_Valid,Down_Valid,Deformation_Valid] = Type_Block(Block,R_Num);
            set(op,'backgroundcolor',Bule_color);
        end
        
    case 'downarrow'
        
        Speed = 0.01;
        
    case 'space'
        
        %变形声音
        Play_Sound(2);
        
        [op,Left_Valid,Right_Valid,Bottom_Valid,Down_Valid,Deformation_Valid] = Type_Block(Block,R_Num);
        if Deformation_Valid ~= 1
            set(op,'backgroundcolor',Grey_color);
            
            Shift_Num = Shift_Num+1;
            if Shift_Num == 5
                Shift_Num = 1;
            end
            
            [op,Left_Valid,Right_Valid,Bottom_Valid,Down_Valid,Deformation_Valid] = Type_Block(Block,R_Num);
            if Deformation_Valid == 1
                Shift_Num = Shift_Num - 1;
                if Shift_Num == 0
                    Shift_Num = 4;
                end
                [op,Left_Valid,Right_Valid,Bottom_Valid,Down_Valid,Deformation_Valid] = Type_Block(Block,R_Num);
            end
            set(op,'backgroundcolor',Bule_color);
        end
        
end

end

4、按键控制

        按键控制可以实现游戏的开始、暂停、重新开始功能。

4.1、开始游戏

        按下开始游戏按键后,方块开始下降。

%开始游戏按键
Pb_start = uicontrol(F,'style','pushbutton',...
    'position',[Pb_start_x,Pb_start_y,Pb_start_length,Pb_start_high],...
    'string','开始游戏');
        
set(Pb_start,...
    'FontName','微软雅黑',...
    'FontSize',10,'FontWeight','bold');

4.2、暂停游戏

        按下暂停游戏按键后,方块运动停止。

%重新开始按键
Pb_reset = uicontrol(F,'style','pushbutton',...
    'position',[Pb_reset_x,Pb_reset_y,Pb_reset_length,Pb_reset_high],...
    'string','重新开始');
        
set(Pb_reset,...
    'FontName','微软雅黑',...
    'FontSize',10,'FontWeight','bold');

set(Pb_reset,'enable','off');

4.3、重新开始

        游戏结束后,可以选择重新开始再次进行游戏。

%暂停按键
Pb_pause = uicontrol(F,'style','pushbutton',...
    'position',[Pb_pause_x,Pb_pause_y,Pb_pause_length,Pb_pause_high],...
    'string','暂停游戏');
        
set(Pb_pause,...
    'FontName','微软雅黑',...
    'FontSize',10,'FontWeight','bold');

5、美化界面

        为了增加游戏的可玩性与观赏性,增加了得分统计、背景图片、开始游戏动画、游戏背景音乐。

5.1、得分统计

        游戏没得一分,就会在框中显示提高一分,并且设置了一个数据库来保存最高得分,每次开始游戏后均会加载最高得分。代码如下:

% 得分统计框文本
Rec_Score_Block_Txt = uicontrol(F,'style','text',...
    'position',[Rec_Score_x_Txt,Rec_Score_y_Txt,Rec_Score_Length_Txt,Rec_Score_High_Txt],...
    'backgroundcolor',Grey_color);
        
        
set(Rec_Score_Block_Txt,'string','当前得分',...
    'FontName','微软雅黑',...
    'FontSize',16,'FontWeight','bold');

      
%得分统计框
Rec_Score_Block = uicontrol(F,'style','text',...
            'position',[Rec_Score_x,Rec_Score_y,Rec_Score_Length,Rec_Score_High],...
            'backgroundcolor',Grey_color);
        
set(Rec_Score_Block,'string',num2str(Rec_Score),...
    'FontName','微软雅黑',...
    'FontSize',16,'FontWeight','bold');

%历史最高得分文本
Rec_Score_Block_max_Txt = uicontrol(F,'style','text',...
            'position',[Rec_Score_max_x_Txt,Rec_Score_max_y_Txt,Rec_Score_max_Length_Txt,Rec_Score_max_High_Txt],...
            'backgroundcolor',Grey_color);
        
set(Rec_Score_Block_max_Txt,'string','历史最高',...
    'FontName','微软雅黑',...
    'FontSize',16,'FontWeight','bold');

%历史最高得分
load('Rec_Score_max.mat');

5.2、背景图片

        在界面后加入一个卡通图片,增加趣味性,代码如下:

ha = axes('units','normalized','pos',[0 0 1 1]);
uistack(ha,'bottom');
ii = imread('风景.jpg');
image(ii);
colormap gray
set(ha,'handlevisibility','off','visible','off');

5.3、开始游戏动画

        开始游戏后,会显示一次动画,代码如下所示:

%开始动画
for j = 1:29
    Play_Sound(3);
    for i = 1:19 
        pause(0.002);
        set(Block(i,j),'backgroundcolor',Type_color(5,:));
    end
end

pause(1);
Play_Sound(2);
Xiao = [Block(2,27);Block(3,26);Block(4,25);Block(5,28);Block(5,27);Block(5,26);Block(5,25);Block(6,25);Block(7,26);Block(8,27);...
    Block(1,24);Block(2,24);Block(3,24);Block(4,24);Block(5,24);Block(6,24);Block(7,24);Block(8,24);Block(9,24);...
    Block(1,23);Block(1,22);Block(1,21);Block(1,20);Block(1,19);Block(1,18);Block(1,17);Block(1,16);Block(1,15);...
    Block(9,23);Block(9,22);Block(9,21);Block(9,20);Block(9,19);Block(9,18);Block(9,17);Block(9,16);Block(9,15);...
    Block(2,21);Block(3,21);Block(4,21);Block(5,21);Block(6,21);Block(7,21);Block(8,21);...
    Block(2,18);Block(3,18);Block(4,18);Block(5,18);Block(6,18);Block(7,18);Block(8,18)];
set(Xiao,'backgroundcolor',Type_color(6,:));

pause(1);
Play_Sound(2);
tian = [Block(10,12);Block(11,12);Block(12,12);Block(13,12);Block(14,12);Block(15,12);Block(16,12);Block(17,12);Block(18,12);...
    Block(10,11);Block(10,10);Block(10,9);Block(10,8);Block(10,7);Block(10,6);Block(10,5);Block(10,4);Block(10,3);Block(10,2);...
    Block(18,11);Block(18,10);Block(18,9);Block(18,8);Block(18,7);Block(18,6);Block(18,5);Block(18,4);Block(18,3);Block(18,2);...
    Block(10,3);Block(11,3);Block(12,3);Block(13,3);Block(14,3);Block(15,3);Block(16,3);Block(17,3);Block(18,3);...
    Block(11,8);Block(11,8);Block(12,8);Block(13,8);Block(14,8);Block(15,8);Block(16,8);Block(17,8);Block(18,8);...
    Block(14,4);Block(14,5);Block(14,6);Block(14,7);Block(14,8);Block(14,9);Block(14,10);Block(14,11)];
set(tian,'backgroundcolor',Type_color(6,:));
Play_Sound(2);

pause(1);
for j = 1:29
    Play_Sound(3);
    for i = 1:19
        pause(0.002);
        set(Block(i,j),'backgroundcolor',Grey_color);
    end
end
pause(1);

5.4、游戏背景音乐

        添加游戏背景音乐,方块的下降与消除均存在音乐。代码如下:

function Play_Sound(sound_type)

switch sound_type
    
    %方块下落声音
    case 1
        [x, Fs] = audioread('Sound_down.wav');
        sound(x, Fs);
        
    %成功消除声音
    case 2
        [x, Fs] = audioread('Sound_success.wav');
        sound(x, Fs);
        
    %方块触底声音
    case 3
        [x, Fs] = audioread('Sound_botton.wav');
        sound(x, Fs);
        
    %游戏结束声音
    case 4
        [x, Fs] = audioread('Sound_finish.wav');
        sound(x, Fs);
        
    %变形声音
    case 5
        [x, Fs] = audioread('Sound_shift.wav');
        sound(x, Fs);
        
end

end

为了编写俄罗斯方块游戏,您需要使用MATLAB GUI来创建UI并处理用户操作和游戏逻辑。下面是一个可能的实现方法: 1. 创建一个GUI窗口来承载游戏:使用`figure`函数创建一个新的窗口,并设置其相关属性(如大小、颜色、标题等)。 2. 创建游戏板:使用MATLAB的矩阵来保存游戏板的状态。在游戏开始时,将矩阵初始化为零,表示所有方块未被占用。您可以使用`rectangle`函数将方块画在GUI上。 3. 生成方块:通过随机生成各种形状的方块(如L型、T型、Z型等),并放置在游戏板的顶部开始游戏。您可以使用MATLAB的二维数组来表示方块的形状,以及它们在游戏板上的位置。 4. 处理玩家输入:使用MATLAB的回调函数来响应玩家按键事件。例如,按下“向左”键会移动方块向左,按下“向下”键会让方块下落更快,按下“旋转”键会使方块旋转90度。在处理用户输入时,需要检查这些操作是否合法(例如,方块是否会越界或与其他方块冲突),并更新游戏板的状态。 5. 检查游戏结束:在下落的方块不能在某些方向上继续移动时,会固定到游戏板上。您需要检查是否有整行已被填满,并将它们从游戏板中删除,然后向下移动剩余行。如果新的方块无法放置在游戏板的顶部,那么游戏结束。 6. 更新分数:根据玩家填满的行数,增加分数,并在GUI上显示。 7. 重复步骤3-6,直到游戏结束。 希望这可以帮助您开始编写俄罗斯方块游戏!
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值