大綱
- 遊戲內容
- 製造地圖
- 選擇數字
- 遊戲運作
- 在arcade運作遇到的限制
成果預覽
選擇數字後 可以切換到相對應的顏色
按下A鍵後從箭頭處開始變色 想辦法讓畫面變成相同顏色
遊戲連結
製造地圖
我們用上回講過的地圖生成函數改寫一下。
這邊要提醒一下arcade的特性,
在宣告陣列的時候不能是空陣列
所以我先在裡面塞東西。
// 地圖初始化
let map = [[0],[0]];
map = []
for (let i = 0; i < map_width; i++) {
map.push([]);
for (let j = 0; j < map_height; j++) {
map[i].push(0);
}
}
然後執行地圖生成,這些都是上回講過的,這邊就不細講了
// 生成斑點
function make_area(x:number, y:number, area_color:number, count:number) {
let now_x = x; // 生成斑點的x座標
let now_y = y; // 生成斑點的y座標
for (let i = 0; i < count; i++) { // 嘗試生成count次
if (map[now_x][now_y] == area_color) { // 如果已經是目標顏色,則不再生成
i + 1;
}
map[now_x][now_y] = area_color; // 生成斑點
let direction = Math.floor(Math.random() * 4); // 隨機製造下次生成的方向
if (direction == 0 && now_x > 0) {
now_x -= 1;
} else if (direction == 1 && now_x < map.length - 1) {
now_x += 1;
} else if (direction == 2 && now_y > 0) {
now_y -= 1;
} else if (direction == 3 && now_y < map.length - 1) {
now_y += 1;
}
}
}
// 地圖生成
function create_map() {
for (let i = 0; i < map.length; i++) {
for (let j = 0; j < map.length; j++) {
if (Math.random() > dispersion * 0.95) { // 有機率生成斑點
make_area(i, j, Math.floor(Math.random() * color_number-1)+1, Math.floor((Math.random() + 1) * 5) * dispersion);
}
}
}
}
最後輸出地圖。
這個輸出的部份我們不像在console一樣是用文字輸出。
所以我們先建立地圖物件
let map_object = sprites.create(img`
...
`, SpriteKind.Player)
map_object.setScale(8, ScaleAnchor.Middle)
map_object.setPosition(115, 100)
用map_object.setScale(8, ScaleAnchor.Middle)
設定物件像素比例
用map_object.setPosition(115, 100)
設定地圖位置
然後是改變地圖圖片
function print_map() {
let create_map = image.create(map_width, map_height)
for (let i = 0; i < map.length; i++) {
for (let j = 0; j < map.length; j++) {
if(map[i][j] == 0){
create_map.setPixel(i, j, 10)
}else{
create_map.setPixel(i, j, map[i][j])
}
}
}
map_object.setImage(create_map)
}
創建一個圖片let creat_map = image.create(map_width, map_height)
設定像素顏色create_map.setPixel(i, j, color)
下面這段的部分是因為arcade的0顏色是代表透明色 所以我將它改為代碼10的顏色
if(map[i][j] == 0){
create_map.setPixel(i, j, 10)
}else{
create_map.setPixel(i, j, map[i][j])
}
最後再讓地圖物件的圖片改為剛剛的create_map
就完成地圖的顯示了
改變數字
構思
偵測按鍵按壓事件 > 改變數字 > 在畫面中視覺化
有了構思就可以開始實作了
controller.right.onEvent(ControllerButtonEvent.Pressed, function () {
...
})
controller.left.onEvent(ControllerButtonEvent.Pressed, function () {
...
})
上面的函式是取得右鍵的按鍵事件,
如果左鍵被按下就會執行裡面的調用函式。
下面則是左鍵。
接下來要在裡面做一些事
可以看到上圖,數字從零開始往右遞增。
所以我們宣告一個變數用來存取現在的數字。
let now_number = 0
然後往右+1往左-1。
再來,我們的數字只有0到9我們不能讓數字超過,
所以我們利用取餘的方式替代if判斷式。
蝦你說用if會更簡單喔? 我單純想秀不行嗎XD
controller.right.onEvent(ControllerButtonEvent.Pressed, function () {
now_number = (now_number + 1) % 10
})
controller.left.onEvent(ControllerButtonEvent.Pressed, function () {
now_number = (10+(now_number-1))%10
})
接下來就是顯示出來啦
創立一個陣列儲存圖片
let chose_number_img = [
img`
...
`,
img`
...
`,
...
]
然後在處理完數字加減後變更圖片
這邊用到object.setImage(Img)
更換物件圖片
controller.right.onEvent(ControllerButtonEvent.Pressed, function () {
now_number = (now_number + 1) % 10
chose_number.setImage(chose_number_img[now_number])
})
controller.left.onEvent(ControllerButtonEvent.Pressed, function () {
now_number = (now_number + 1) % 10
chose_number.setImage(chose_number_img[now_number])
})
這樣選擇的部分就告一段落了。
遊戲運作
//main
create_map(); // 生成地圖
print_map(); // 輸出地圖
開始時先呼叫函數
再來是實際玩的部分
一樣,先做構想
按下A鍵後 > 傳入now_number > 執行flood fill演算法 > 改變圖片
controller.A.onEvent(ControllerButtonEvent.Pressed, function () {
flood_fill(map[0][0], now_number, 0, 0)
print_map()
if (check_end()) { // 檢查是否結束
console.log("you win");
game.over(true)
}
})
所我們每次按下A鍵的時候執行flood fill
演算法改變map陣列
再來執行print_map
將結果印出來
最後看看是否都是同一個顏色了,結束了就結束遊戲。
檢查函數就沒甚麼好說的了,各位看看應該就懂了。
// 檢查是否結束
function check_end() {
let end = true;
let color = map[0][0]; // 設定初始顏色
for (let i = 0; i < map.length; i++) {
for (let j = 0; j < map.length; j++) {
if (map[i][j] != color) { // 如果有不同的顏色,則還沒結束
end = false;
return end;
}
}
}
return end;
}
恭喜各位看到這裡,基本上遊戲就做完啦!
不過有人想說這地圖有點小,我可以增加難度讓地圖變大嗎?
在arcade運作遇到的限制
各位還記的上回我說過flood fill
是怎麼運作的嗎?
沒錯是用遞迴的方式。
所以有學過遞迴的現在應該想到一件事,遞迴有層數限制。
但在python或是javascript本身理論上可以跑到九百多層。
不過各位的arcade機是用單片機運作的,效能跟電腦差了好幾倍。
說到這邊大家應該理解了。沒錯!arcade的遞迴層數沒有很多,具體有多少我沒有實測。
不過你如果地圖太大會讓搜尋的時候遞迴太多層,導致程式直接被kill掉。
目前這個大小算式在可以邊緣,有可能會被kill不過大部分時間是可以完成遊戲的。
下期預告
各種棋篇
>_一篇文章教你製作連線相關的棋類
黑白棋 立體四子棋 圈圈叉叉