在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

基于JAVA UI開發的“推箱子”小游戲

OpenHarmony技術社區 ? 來源:OpenHarmony技術社區 ? 2023-01-05 09:32 ? 次閱讀

本文我們將逐步分享基于 JAVA UI 開發的“推箱子”小游戲這個項目的構建流程。

實際上,筆者在進行開發的過程中,并不是寫完一個界面的內部邏輯,就開始對界面進行美化,而是先讓所有的東西可以正常地跑起來,再談美化。

因此本系列文章前半部分會重點討論游戲以及界面之間的核心邏輯,后半部分則會分享美化界面的部分。

項目創建

打開 DevEco Studio,創建一個新項目,選擇 JAVA 作為開發語言,將項目保存至合適的位置。

11a68738-8c76-11ed-bfe3-dac502259ad0.png

根據上期分享的開發思路,先完成 UI 交互部分的框架。

11bbd4c6-8c76-11ed-bfe3-dac502259ad0.png

可以看到,這里需要新建三個 Slice(原本自帶一個 MainAbilitySlice):

11db0d46-8c76-11ed-bfe3-dac502259ad0.png

下面對四個 UI 交互功能進行講解。MainAbilitySlice:打開應用時,首先顯示的界面,也就是用戶主界面。11e85aaa-8c76-11ed-bfe3-dac502259ad0.png

SelectSlice:關卡選擇界面,用戶可以在這個界面選擇將要跳轉的關卡。

11f29312-8c76-11ed-bfe3-dac502259ad0.png

InitSlice:加載界面。當用戶選擇關卡之后,會進入加載界面,仿照游戲加載資源。(實際上啥都沒干)

11f99c7a-8c76-11ed-bfe3-dac502259ad0.pngGameSlice:最后一個界面,也就是這個游戲的核心界面,所有的游戲邏輯都將在這個頁面中進行,因此它將是本篇文章的核心講解部分。1201f4a6-8c76-11ed-bfe3-dac502259ad0.png

至此,我們可以簡單地梳理一下四個界面以及他們包含的組件之間的關系:用戶進入 MainAbilitySlice 之后,通過“開始游戲”按鍵進入 SelectSlice。

在 SelectSlice 中有三個按鍵,會對應跳轉到三個不同的關卡,但是進入關卡之前會先進入 InitSlice,加載過后在進入最后的 GameSlice,從而開始游戲。以上就是開發的時候要理清楚的頁面跳轉關系。

核心代碼分析

①MainAbilitySlice

里面有四個按鈕,那可以簡單的給他們分個類,例如:開始游戲的按鈕要實現的功能是頁面跳轉,直接與其他界面關聯,分為一類。

歷史記錄與關于游戲可以用彈出窗口來實現,不需要額外界面,歸為一類;退出游戲按鈕直接結束應用進程,也是單獨一類。

明確之后,就可以給各個按鈕添加點擊事件了:

//開始游戲按鈕
startBtn.setClickedListener(newComponent.ClickedListener(){
@Override
publicvoidonClick(Componentcomponent){
//頁面跳轉
present(newSelectSlice(),newIntent());
}
});
//歷史記錄按鈕
recordBtn.setClickedListener(newComponent.ClickedListener(){
@Override
publicvoidonClick(Componentcomponent){
//歷史記錄彈窗
}
});
//關于游戲按鈕
aboutBtn.setClickedListener(newComponent.ClickedListener(){
@Override
publicvoidonClick(Componentcomponent){
//關于游戲彈窗
}
});
//退出游戲按鈕
exitBtn.setClickedListener(newComponent.ClickedListener(){
@Override
publicvoidonClick(Componentcomponent){
//退出游戲提示
CommonDialogcommonDialog=newCommonDialog(getContext());
commonDialog.setTitleText("提示");
commonDialog.setContentText("是否退出游戲");
commonDialog.setButton(1,"確定",newIDialog.ClickedListener(){
@Override
publicvoidonClick(IDialogiDialog,inti){
terminateAbility();
}
});
commonDialog.setButton(2,"取消",newIDialog.ClickedListener(){
@Override
publicvoidonClick(IDialogiDialog,inti){
commonDialog.destroy();
}
});
commonDialog.show();
}
});
在開發中,由于歷史記錄跟關于游戲這兩個功能并不是核心,因此,最開始也只是做個殼子放在這,以便自己能專注于游戲主邏輯的開發,這也是我想分享的一種思路:先搭殼子再填東西。因此,閱讀本系列時,如果碰到代碼中只有注釋,沒有實現內容時,那是因為當時做到這一步的時候,并不會去關注具體如何實現,只會想個大概,先放著。到這里之后,實際上已經完成了游戲的退出以及從 MainAbilitySlice 頁面到 SelectSlice 頁面的導航,便可進行到我們的下一步。

②SelectSlice

這一個界面主要有三個按鈕,如何實現按下不同的按鈕,跳轉到同一個加載界面,但是加載完后又跳轉到不同的游戲界面?

這里使用 Intent 對跳轉時的數據進行打包傳輸,具體實現如下:

firstBtn.setClickedListener(newComponent.ClickedListener(){
@Override
publicvoidonClick(Componentcomponent){
Intenti=newIntent();
i.setParam("關卡",1);
present(newInitSlice(),i);
}
});
secondBtn.setClickedListener(newComponent.ClickedListener(){
@Override
publicvoidonClick(Componentcomponent){
Intenti=newIntent();
i.setParam("關卡",2);
present(newInitSlice(),i);
}
});
thirdBtn.setClickedListener(newComponent.ClickedListener(){
@Override
publicvoidonClick(Componentcomponent){
Intenti=newIntent();
i.setParam("關卡",3);
present(newInitSlice(),i);
}
});
這里 Intent 的 key 都是“關卡”,但是有不同的 value,對應不同的關卡。實際上,到這里 SelectSlice 已經完成了它的功能了。接下來進入 InitSlice。③InitSlice在加載界面中,我預想的是一個動態的畫面,然后加上一個進度條,因此我可能需要用到能夠播放 gif 的組件,以及進度條組件。

那要怎么實現加載的時候進度條跟進?我的實現方式是使用兩個定時器(其實用一個也完全能搞定)

//onStart外定義
Timert1=newTimer();
Timert2=newTimer();
//onStart內
TimerTasktask1=newTimerTask(){
@Override
publicvoidrun(){
//頁面跳轉
present(newGameSlice(),intent);
}
};
TimerTasktask2=newTimerTask(){
@Override
publicvoidrun(){
//進度條更新
intvalue=progressBar.getProgress();
progressBar.setProgressValue(value+20);
}
};
t1.schedule(task1,5000);
t2.schedule(task2,0,1000);
關于如何播放 gif,本不應該在此講解,因為與主線任務無關,但是這里用到的第三方組件,后面游戲界面頻繁使用,因此在這進行介紹。

這里用到了第三方組件 Glide,關于組件如何使用,可具體看這篇文章,只需幾行代碼即可完成 gif 的播放,十分方便。

https://ost.51cto.com/posts/8635
intimageResourceId=ResourceTable.Media_gifimg;
Glide.with(this)
.asGif()
.load(imageResourceId)
.into(draweeView);
至此,從 InitSlice 跳轉到 GameSlice 的邏輯也寫好了,并且攜帶著從 SelectSlice 打包過來的數據,接下來重點講解游戲界面的實現。④GameSlice制作一個可以玩的游戲界面最首要的任務就是繪制地圖,因此定義了一個 JAVA 類 GameMap 用于地圖的繪制。在說明如何實現 GameMap 之前,我想先簡單闡述一下推箱子游戲的實現邏輯:實際上每一次操作的都是圖片,邏輯判斷依賴的是圖片所綁定的屬性值(只涉及加減運算)。舉個例子:我在程序中將路設置為 0,將墻體設置為 1,將寶可夢設置為 2 和 3,將空球設置為 4,那收服之后的球應該設置為:2+4=6、3+4=7,這樣就實現了你把空球推向寶可夢時,顯示的是已經收復的球的狀態。而如果將人設置為 8,那 8+2=10、8+3=11 也必須是人,這樣才能實現你移動到寶可夢上面時,是以原人物的方式呈現。這是在設置屬性值需要注意的,其他方面,例如怎么判斷墻體之類的,只需要 if 語句判斷即可。還有一點,如果我們要實現回退功能,就需要用到棧的一些相關操作。

核心代碼如下:

//GameMap繼承于PositionLayout布局,方便對圖片進行渲染
publicclassGameMapextendsPositionLayout{

privatefinalstaticintsize=110;

//用二維數組來存儲地圖
privateInteger[][]gameMap;
//定義x,y坐標
privatePairmap_position;
//標識是否繪制過地圖(畫過一次后,后面所有的操作都只能是進行刷新,防止重復生成對象)
privateBooleanisDrew=Boolean.FALSE;
//定義移動方式枚舉,方便外部調用進行選擇
publicenumMOVE_WAY{
MOVE_UP,
MOVE_DOWN,
MOVE_LEFT,
MOVE_RIGHT
}

//設置每種物體的屬性值
privatefinalstaticintROAD=0;
privatefinalstaticintWALL=1;

privatefinalstaticintLABA=2;
privatefinalstaticintYIBU=3;
privatefinalstaticintBOBO=4;
privatefinalstaticintMINI=5;
privatefinalstaticintMIAO=6;

privatefinalstaticintBALL_EMPTY=7;
privatefinalstaticintBALL_FULL1=9;
privatefinalstaticintBALL_FULL2=10;
privatefinalstaticintBALL_FULL3=11;
privatefinalstaticintBALL_FULL4=12;
privatefinalstaticintBALL_FULL5=13;
privatefinalstaticintPEOPLE1=14;
privatefinalstaticintPEOPLE2=16;
privatefinalstaticintPEOPLE3=17;
privatefinalstaticintPEOPLE4=18;
privatefinalstaticintPEOPLE5=19;
privatefinalstaticintPEOPLE6=20;
//定義存儲地圖用的棧
privateStackstack;
//可使用此構造函數繪制不同大小的地圖,這個是預留的接口,項目中使用的是直接在xml文件中加入這個組件(因為繼承了PositionLayout所以可以在xml文件中使用),當然也可以直接用構造函數創建,留給讀者自己發揮。
publicGameMap(Contextcontext,Integer[][]map,intx,inty){
super(context);
gameMap=map;
map_position=newPair<>(x,y);
}
//外部設置地圖接口
publicvoidsetMap(Integer[][]map){
gameMap=map;
map_position=newPair<>(map.length,map[0].length);
stack=newStack<>();
}
//繪制地圖接口
publicvoiddrawMap(){
setHeight(size*map_position.s);
setWidth(size*map_position.f);
for(inti=0;ifor(intj=0;jnewDraweeView(getContext());
draweeView.setComponentSize(size,size);
draweeView.setContentPosition(size*j,size*i);
intindex=gameMap[i][j];
switch(index){
caseROAD:
Glide.with(getContext())
.load(ResourceTable.Media_road)
.diskCacheStrategy(DiskCacheStrategy.NONE)
.skipMemoryCache(true)
.into(draweeView);
break;
caseWALL:
Glide.with(getContext())
.load(ResourceTable.Media_wall)
.diskCacheStrategy(DiskCacheStrategy.NONE)
.skipMemoryCache(true)
.into(draweeView);
break;
caseLABA:
Glide.with(getContext())
.load(ResourceTable.Media_laba)
.diskCacheStrategy(DiskCacheStrategy.NONE)
.skipMemoryCache(true)
.into(draweeView);
break;
caseYIBU:
Glide.with(getContext())
.load(ResourceTable.Media_yibu)
.diskCacheStrategy(DiskCacheStrategy.NONE)
.skipMemoryCache(true)
.into(draweeView);
break;
caseBOBO:
Glide.with(getContext())
.load(ResourceTable.Media_bobo)
.diskCacheStrategy(DiskCacheStrategy.NONE)
.skipMemoryCache(true)
.into(draweeView);
break;
caseMINI:
Glide.with(getContext())
.load(ResourceTable.Media_mini)
.diskCacheStrategy(DiskCacheStrategy.NONE)
.skipMemoryCache(true)
.into(draweeView);
break;
caseMIAO:
Glide.with(getContext())
.load(ResourceTable.Media_miao)
.diskCacheStrategy(DiskCacheStrategy.NONE)
.skipMemoryCache(true)
.into(draweeView);
break;
caseBALL_EMPTY:
Glide.with(getContext())
.load(ResourceTable.Media_ballEmpty)
.diskCacheStrategy(DiskCacheStrategy.NONE)
.skipMemoryCache(true)
.into(draweeView);
break;
caseBALL_FULL1:
caseBALL_FULL2:
caseBALL_FULL3:
caseBALL_FULL4:
caseBALL_FULL5:
Glide.with(getContext())
.load(ResourceTable.Media_ballFull)
.diskCacheStrategy(DiskCacheStrategy.NONE)
.skipMemoryCache(true)
.into(draweeView);
break;
casePEOPLE1:
casePEOPLE2:
casePEOPLE3:
casePEOPLE4:
casePEOPLE5:
casePEOPLE6:
Glide.with(getContext())
.load(ResourceTable.Media_people)
.diskCacheStrategy(DiskCacheStrategy.NONE)
.skipMemoryCache(true)
.into(draweeView);
break;
}

this.addComponent(draweeView);
}
}
isDrew=Boolean.TRUE;
}
//外部刷新地圖接口
publicvoidflushMap(){
for(inti=0;ifor(intj=0;jintindex=gameMap[i][j];
switch(index){
caseROAD:
Glide.with(getContext())
.load(ResourceTable.Media_road)
.diskCacheStrategy(DiskCacheStrategy.NONE)
.skipMemoryCache(true)
.into(draweeView);
break;
caseWALL:
Glide.with(getContext())
.load(ResourceTable.Media_wall)
.diskCacheStrategy(DiskCacheStrategy.NONE)
.skipMemoryCache(true)
.into(draweeView);
break;
caseLABA:
Glide.with(getContext())
.load(ResourceTable.Media_laba)
.diskCacheStrategy(DiskCacheStrategy.NONE)
.skipMemoryCache(true)
.into(draweeView);
break;
caseYIBU:
Glide.with(getContext())
.load(ResourceTable.Media_yibu)
.diskCacheStrategy(DiskCacheStrategy.NONE)
.skipMemoryCache(true)
.into(draweeView);
break;
caseBOBO:
Glide.with(getContext())
.load(ResourceTable.Media_bobo)
.diskCacheStrategy(DiskCacheStrategy.NONE)
.skipMemoryCache(true)
.into(draweeView);
break;
caseMINI:
Glide.with(getContext())
.load(ResourceTable.Media_mini)
.diskCacheStrategy(DiskCacheStrategy.NONE)
.skipMemoryCache(true)
.into(draweeView);
break;
caseMIAO:
Glide.with(getContext())
.load(ResourceTable.Media_miao)
.diskCacheStrategy(DiskCacheStrategy.NONE)
.skipMemoryCache(true)
.into(draweeView);
break;
caseBALL_EMPTY:
Glide.with(getContext())
.load(ResourceTable.Media_ballEmpty)
.diskCacheStrategy(DiskCacheStrategy.NONE)
.skipMemoryCache(true)
.into(draweeView);
break;
caseBALL_FULL1:
caseBALL_FULL2:
caseBALL_FULL3:
caseBALL_FULL4:
caseBALL_FULL5:
Glide.with(getContext())
.load(ResourceTable.Media_ballFull)
.diskCacheStrategy(DiskCacheStrategy.NONE)
.skipMemoryCache(true)
.into(draweeView);
break;
casePEOPLE1:
casePEOPLE2:
casePEOPLE3:
casePEOPLE4:
casePEOPLE5:
casePEOPLE6:
Glide.with(getContext())
.load(ResourceTable.Media_people)
.diskCacheStrategy(DiskCacheStrategy.NONE)
.skipMemoryCache(true)
.into(draweeView);
break;
}

}
}
}
//獲取當前操作的人物坐標
publicPairgetMyPosition(){
for(inti=0;ifor(intj=0;jif(gameMap[i][j]==PEOPLE1||gameMap[i][j]==PEOPLE2||
gameMap[i][j]==PEOPLE3||gameMap[i][j]==PEOPLE4||
gameMap[i][j]==PEOPLE5||gameMap[i][j]==PEOPLE6)
{
returnnewPair<>(i,j);
}

}
}
returnnewPair<>(-1,-1);
}
//給地圖里任意一張圖設置對應的值,移動的時候需要此接口
protectedvoidsetValue(intx,inty,intvalue){
gameMap[x][y]+=value;
}
//判斷是否能夠移動
protectedBooleanisMove(inti,intj){
if(gameMap[i][j]==ROAD||gameMap[i][j]==LABA||
gameMap[i][j]==YIBU||gameMap[i][j]==BOBO||
gameMap[i][j]==MINI||gameMap[i][j]==MIAO)
returnBoolean.TRUE;
returnBoolean.FALSE;
}
//判斷是不是球
protectedBooleanisBall(inti,intj){
if(gameMap[i][j]==BALL_EMPTY||gameMap[i][j]==BALL_FULL1||
gameMap[i][j]==BALL_FULL2||gameMap[i][j]==BALL_FULL3||
gameMap[i][j]==BALL_FULL4||gameMap[i][j]==BALL_FULL5)
{
returntrue;
}
returnBoolean.FALSE;
}
//外部接口,每一次移動完判斷游戲是否結束
publicBooleanisWin(){
for(inti=0;ifor(intj=0;jif(gameMap[i][j]==LABA||gameMap[i][j]==YIBU||
gameMap[i][j]==BOBO||gameMap[i][j]==MINI||
gameMap[i][j]==MIAO)returnBoolean.FALSE;
}
}
returnBoolean.TRUE;
}
//外部移動接口
publicvoidmove(@NotNullMOVE_WAYmove_way){
Pairposition=getMyPosition();
Integer[][]oldMap=newInteger[map_position.f][map_position.s];
for(inti=0;iif(map_position.s>=0)System.arraycopy(gameMap[i],0,oldMap[i],0,map_position.s);
}

stack.push(oldMap);
switch(move_way){
caseMOVE_UP:
if(this.isMove(position.f-1,position.s))
{
this.setValue(position.f,position.s,-PEOPLE1);
this.setValue(position.f-1,position.s,PEOPLE1);
}
if(this.isBall(position.f-1,position.s))
{
if(this.isMove(position.f-2,position.s))
{
this.setValue(position.f,position.s,-PEOPLE1);
this.setValue(position.f-1,position.s,BALL_EMPTY);
this.setValue(position.f-2,position.s,BALL_EMPTY);
}
}
break;
caseMOVE_DOWN:
if(this.isMove(position.f+1,position.s))
{
this.setValue(position.f,position.s,-PEOPLE1);
this.setValue(position.f+1,position.s,PEOPLE1);
}
if(this.isBall(position.f+1,position.s))
{
if(this.isMove(position.f+2,position.s))
{
this.setValue(position.f,position.s,-PEOPLE1);
this.setValue(position.f+1,position.s,BALL_EMPTY);
this.setValue(position.f+2,position.s,BALL_EMPTY);
}
}
break;
caseMOVE_LEFT:
if(this.isMove(position.f,position.s-1))
{
this.setValue(position.f,position.s,-PEOPLE1);
this.setValue(position.f,position.s-1,PEOPLE1);
}
if(this.isBall(position.f,position.s-1))
{
if(this.isMove(position.f,position.s-2))
{
this.setValue(position.f,position.s,-PEOPLE1);
this.setValue(position.f,position.s-1,BALL_EMPTY);
this.setValue(position.f,position.s-2,BALL_EMPTY);
}
}
break;
caseMOVE_RIGHT:
if(this.isMove(position.f,position.s+1))
{
this.setValue(position.f,position.s,-PEOPLE1);
this.setValue(position.f,position.s+1,PEOPLE1);
}
if(this.isBall(position.f,position.s+1))
{
if(this.isMove(position.f,position.s+2))
{
this.setValue(position.f,position.s,-PEOPLE1);
this.setValue(position.f,position.s+1,BALL_EMPTY);
this.setValue(position.f,position.s+2,BALL_EMPTY);
}
}
break;
}
flushMap();
}
//外部回退原先地圖接口
publicvoidback(){
if(stack.empty())return;
Integer[][]temp=stack.peek();
for(inti=0;iif(map_position.s>=0)System.arraycopy(temp[i],0,gameMap[i],0,map_position.s);
}
flushMap();
stack.pop();
}

publicBooleangetIsDrew(){
returnisDrew;
}

publicGameMap(Contextcontext){
super(context);
}

publicGameMap(Contextcontext,AttrSetattrSet){
super(context,attrSet);
}

publicGameMap(Contextcontext,AttrSetattrSet,StringstyleName){
super(context,attrSet,styleName);
}
}
至此,完成了地圖類的代碼,可以開始繪制 GameSlice 了。在預覽圖中看到,核心部分有很多:一個退出界面按鈕,一個設置按鈕,一個倒計時器,還有一張地圖,一個后退地圖操作的按鈕,按照我自己的想法先進行分類。

后退地圖操作的按鈕和地圖是剛需,優先實現,代碼如下:

//在外部定義變量
floatstart_x;
floatstart_y;

Integer[][]map;
Integer[][]map1={
{1,1,1,1,1,1,1,1,1},
{1,0,0,0,1,0,0,1,1},
{1,0,1,0,1,7,2,1,1},
{1,0,0,0,0,7,3,1,1},
{1,0,1,0,1,7,4,1,1},
{1,0,0,0,1,0,0,1,1},
{1,1,1,1,1,0,14,1,1},
{1,1,1,1,1,1,1,1,1},
{1,1,1,1,1,1,1,1,1}
};
Integer[][]map2={
{1,1,1,1,1,1,1,1,1},
{1,1,1,1,1,1,1,1,1},
{1,1,0,0,0,3,0,1,1},
{1,1,0,1,0,1,0,1,1},
{1,1,0,7,14,7,0,1,1},
{1,1,0,1,0,1,5,1,1},
{1,1,0,7,6,0,0,1,1},
{1,1,1,1,1,1,1,1,1},
{1,1,1,1,1,1,1,1,1}
};
Integer[][]map3={
{1,1,1,1,1,1,1,1,1},
{1,1,1,1,1,1,1,1,1},
{1,0,2,0,7,0,1,1,1},
{1,1,0,7,6,7,0,1,1},
{1,3,4,5,1,0,5,1,1},
{1,0,1,7,0,7,0,1,1},
{1,0,7,0,1,2,7,1,1},
{1,0,14,0,0,0,0,1,1},
{1,1,1,1,1,1,1,1,1}
};

//onStart方法內

switch(intent.getIntParam("關卡",0))
{
case1:
map=map1;
break;
case2:
map=map2;
break;
case3:
map=map3;
break;
}
gameMap.setMap(map);
if(!gameMap.getIsDrew())gameMap.drawMap();
elsegameMap.flushMap();

//滑動屏幕移動角色
gameMap.setTouchEventListener(newComponent.TouchEventListener(){
@Override
publicbooleanonTouchEvent(Componentcomponent,TouchEventtouchEvent){
intaction=touchEvent.getAction();
switch(action){
caseTouchEvent.PRIMARY_POINT_DOWN:
MmiPointstartPoint=touchEvent.getPointerPosition(0);
start_x=startPoint.getX();
start_y=startPoint.getY();
break;
caseTouchEvent.PRIMARY_POINT_UP:
MmiPointendPoint=touchEvent.getPointerPosition(0);
if(endPoint.getX()>start_x&&Math.abs(endPoint.getY()-start_y)100){//right
gameMap.move(GameMap.MOVE_WAY.MOVE_RIGHT);
}
elseif(endPoint.getX()abs(endPoint.getY()-start_y)100){//left
gameMap.move(GameMap.MOVE_WAY.MOVE_LEFT);
}
elseif(endPoint.getY()abs(endPoint.getX()-start_x)100){//up
gameMap.move(GameMap.MOVE_WAY.MOVE_UP);
}
elseif(endPoint.getY()>start_y&&Math.abs(endPoint.getX()-start_x)100){//down
gameMap.move(GameMap.MOVE_WAY.MOVE_DOWN);
}
if(gameMap.isWin()){
//贏了之后該干嘛

}
break;
}
returntrue;
}

});
stackBtn.setClickedListener(newComponent.ClickedListener(){
@Override
publicvoidonClick(Componentcomponent){
gameMap.back();
}
});
游戲整體框架(不包括數據存儲)大概就是這些,至此,已經實現了這個游戲最基礎的功能了,從開始界面到游戲界面,以及各種游戲操作,接下來的事情就是對這些零零散散的組件。

用一個漂亮的布局整合起來,再根據自己的興趣添加一些其他功能,下篇將重點給出美化 UI 交互界面的代碼,敬請期待!

審核編輯 :李倩


聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 應用
    +關注

    關注

    2

    文章

    439

    瀏覽量

    34431
  • JAVA
    +關注

    關注

    20

    文章

    2984

    瀏覽量

    106900
  • 代碼
    +關注

    關注

    30

    文章

    4887

    瀏覽量

    70262
收藏 人收藏

    評論

    相關推薦
    熱點推薦

    鴻蒙5開發寶藏案例分享---一多開發實例(游戲

    十年前藏的現金一樣驚喜!)這些藏在文檔深處的\"武功秘籍\",能幫我們輕松實現分布式游戲、跨端協同這些聽起來很酷的功能。快上車,帶你解鎖鴻蒙開發的正確姿勢! 一、分布式游戲手柄
    發表于 06-03 18:22

    Java開發者必備的效率工具——Perforce JRebel是什么?為什么很多Java開發者在用?

    Perforce JRebel是一款Java開發效率工具,旨在幫助java開發人員更快地編寫更好的應用程序。JRebel可即時重新加載對代碼的修改,無需重啟或重新部署應用程序,就能讓
    的頭像 發表于 04-27 13:44 ?155次閱讀
    <b class='flag-5'>Java</b><b class='flag-5'>開發</b>者必備的效率工具——Perforce JRebel是什么?為什么很多<b class='flag-5'>Java</b><b class='flag-5'>開發</b>者在用?

    基于RV1126開發板實現簡單的UI開發示例

    本方案為最簡單的UI開發示例,已為用戶初步構建一個基本的應用工程;準備好我司的easyeai-api鏈接調用;準備好UI開發環境。其目的在于方便用戶馬上進行帶有界面交互的產品
    的頭像 發表于 04-18 16:07 ?409次閱讀
    基于RV1126<b class='flag-5'>開發</b>板實現簡單的<b class='flag-5'>UI</b><b class='flag-5'>開發</b>示例

    RV1126 實現簡單的UI開發示例

    在RV1126上實現簡單的UI開發實例
    的頭像 發表于 04-09 16:08 ?284次閱讀
    RV1126 實現簡單的<b class='flag-5'>UI</b><b class='flag-5'>開發</b>示例

    全鏈路賦能游戲鴻蒙化適配,鴻蒙游戲開發者服務煥新升級

    3月14日,華為游戲中心在成都開展了鴻蒙游戲開發者服務日線下活動。本次活動吸引了百余位游戲廠商代表以及開發者參與。華為一線技術專家團隊與眾多
    的頭像 發表于 03-17 09:25 ?372次閱讀
    全鏈路賦能<b class='flag-5'>游戲</b>鴻蒙化適配,鴻蒙<b class='flag-5'>游戲</b><b class='flag-5'>開發</b>者服務煥新升級

    如何安裝模擬器玩nes小游戲-基于米爾瑞芯微RK3576開發

    本篇源自:優秀創作者 小手涼涼本文將介紹基于米爾電子MYD-LR3576開發板(米爾基于瑞芯微 RK3576開發板)的安裝模擬器玩nes小游戲方案測試。 核心板系統 操作系統鏡像文件說明
    發表于 02-08 12:10

    Qt Group發布Qt AI Assistant,助力跨平臺UI開發

    為了進一步提升跨平臺用戶界面(UI)開發的效率與便捷性,Qt Group近日推出了一款實驗性工具——Qt AI Assistant。這款工具的問世,標志著Qt Group在簡化UI開發
    的頭像 發表于 02-07 13:47 ?977次閱讀

    SSM框架在Java開發中的應用 如何使用SSM進行web開發

    SSM框架,即Spring、SpringMVC和MyBatis的整合,是Java Web開發中常用的技術棧。它通過分層架構,實現了視圖、控制、業務邏輯和數據訪問的分離,提高了代碼的可維護性和可擴展性
    的頭像 發表于 12-16 17:28 ?1437次閱讀

    FPGA打磚塊小游戲設計思路

    HDL,?Vivado 平臺上開發打磚塊小游戲并使用 PS2 與 VGA 的基本思路: 一、整體架構設計 1. 輸入模塊: ? PS2 接口模塊:負責與 PS2 設備(如游戲手柄)進行通信,接收手柄
    的頭像 發表于 12-09 16:57 ?793次閱讀

    Java 23功能介紹

    Java 23 包含全新和更新的 Java 語言功能、核心 API 以及 JVM,同時適合新的 Java 開發者和高級開發者。從?Intel
    的頭像 發表于 12-04 10:02 ?846次閱讀
    <b class='flag-5'>Java</b> 23功能介紹

    ChatGPT 在游戲開發中的創新應用

    游戲開發領域,人工智能技術的應用正變得越來越廣泛。ChatGPT,作為一種先進的自然語言處理(NLP)模型,為游戲開發帶來了許多創新的應用。 1. 動態對話系統 ChatGPT的強項
    的頭像 發表于 10-25 18:05 ?993次閱讀

    甲骨文發布Java 23

    全球領先的軟件開發企業甲骨文(Oracle)近日隆重宣布推出Java 23(Oracle JDK 23),這一里程碑式的更新標志著全球排名第一的編程語言和開發平臺再次邁出堅實步伐。Java
    的頭像 發表于 09-19 16:36 ?597次閱讀

    JAE ST12系列/式卡用連接器產品概要

    日本航空電子工業現已開發并推出了符合microSD 卡的/式卡用連接器— “ST12系列”,該連接器適用于智能手機、平板電腦、游戲PC等小型ICT(信息通信技術)設備。
    的頭像 發表于 09-10 10:10 ?556次閱讀
    JAE ST12系列<b class='flag-5'>推</b>/<b class='flag-5'>推</b>式卡用連接器產品概要

    ?介紹一款Java開發的開源MES系統

    ?介紹一款Java開發的開源MES系統,萬界星空科技開源的MES系統。該系統基于Java開發,具有廣泛的適用性和高度的可定制性,能夠滿足不同行業、不同規模企業的智能制造需求。
    的頭像 發表于 09-05 17:39 ?1246次閱讀
    ?介紹一款<b class='flag-5'>Java</b><b class='flag-5'>開發</b>的開源MES系統

    華納云:java web和java有什么區別java web和java有什么區別

    Java Web和Java是兩個不同的概念,它們在功能、用途和實現方式上存在一些區別,下面將詳細介紹它們之間的區別。 1. 功能和用途: – Java是一種編程語言,它提供了一種用于開發
    的頭像 發表于 07-16 13:35 ?1365次閱讀
    華納云:<b class='flag-5'>java</b> web和<b class='flag-5'>java</b>有什么區別<b class='flag-5'>java</b> web和<b class='flag-5'>java</b>有什么區別
    主站蜘蛛池模板: 日本三级最新中文字幕电影 | 成人福利在线视频 | caobi在线观看 | 亚洲成a人片在线观看尤物 亚洲成a人片在线观看中 | 久久精品操 | 亚洲free | 性欧美处| 新四虎影院 | 亚洲影视大全 | 亚洲国产毛片aaaaa无费看 | 美女免费黄 | 香蕉狠狠再啪线视频 | 五月婷婷激情六月 | 海棠高h粗暴调教双性男男 韩国韩宝贝2020vip福利视频 | 五月天婷五月天综合网在线 | 国产伦精品一区二区三区 | 欧美精品啪啪 | 夜色爽爽 | 好爽好黄的视频 | 日本aaaaa| 猛操网 | 亚洲a网站| 久久精品综合网 | 夜夜艹 | 欧洲天堂网 | 中国又粗又大又爽的毛片 | 亚洲国产成人精品不卡青青草原 | 爱操综合网| 天天摸天天做天天爽 | 亚洲欧美视频 | 女人牲交一级毛片 | 亚洲综合久久久 | 在线天堂中文在线网 | 久久狠狠色噜噜狠狠狠狠97 | 亚洲特黄大黄一级毛片 | 四虎影院观看视频 | 亚洲w码欧洲s码免费 | 特黄特黄特色大片免费观看 | 欧美午夜电影 | 亚洲国产婷婷香蕉久久久久久 | 国产yw855.c免费观看网站 |