2017年12月4日月曜日

[Web開發]Node.js 迷航記(express+angular+bootstrap+webpack+webstorm整合開發)

之前寫過的php+mysql的網站,在經過近十年的荒廢之後,對於web開發的認知已成了浦島太郎狀態。加上HTML5+Node.js成了web前後端的熱門顯學,於是想把整個網頁打掉重練。
翻了一陣子相關資料,看到滿滿的套件,還是有一種看不太懂的感覺。

經過一番整理,得到了以下的概念:
web page的運行架構為client/server。
所以定義client(下載到browser顯示的頁面)為「前端」,server為「server端」。

  • Node.js :在「server端」讀取.js檔案並執行,與各個OS介接的執行程式。擁有檔案I/O跟網路I/O(通常拿來做為http server)的功能,可根據不同的uri request執行相對應的回應。
  • npm : node.js package manager. 安裝並管理node.js可利用的各個模組。為node.js初始支援模組。下面提到的所有「server端」使用的模組都需要以npm安裝。
  • express:「server端」以javascript描述server response的模組。還提供了http server設定的template,大幅降低設定的困難度。
    以npm指令:
    npm install -gd express-generator
  • bower:安裝與管理「前端」使用的javascript模組。像是angular / bootstrap... 並把複雜的模組依存架構做成設定檔,讓其他的網頁資料前置處理模組使用。
    但是..........在這個變動快速的世界....bower已經被npm建議改用Yarn了。
  • Yarn:也是一種安裝包的管理軟體。跟npm的功能類似。也是以node.js為執行平台。
  • Karma:執行測試。一些需要做各種條件測試的功能,有測試軟體幫忙跑case會輕鬆很多。
  • AngularJS:「前端」的application framework。有了它,可以輕鬆的架構模組化,資料-顯示-邏輯分離的網頁app。
  • bootstrap:在「前端」幫忙排版網頁的引擎。主要是拿來處理螢幕大小的對應顯示,跟美化各個網頁上的元件。
  • webpack:打包前端的javascript/css/資源(如圖片等等)並加上其他改善處理(例如縮小程式碼/混亂程式碼等等)的模組。在大量應用js模組的時代,在html裡面一個個的用script tag載入是相當麻煩而且沒有效率的事情。而且會導致大量的http request,對server也是負擔。尤其要面對各模組之間的依存順序的時候更會讓你頭痛。因此導入打包模組是必須的。當然,簡單的網頁就不一定要這麼麻煩...


從.頭.開.始。

簡單的了解海量的元件之後,當然是直接要從.頭.開.始。
本文使用OSX為作業環境。
安裝npm: 從官網抓安裝包最安全。 https://nodejs.org/
建立project:在這裡使用express-generator的模板建立流程。
  • 先安裝express-generator:
    sudo npm install -g express-generator
    註:參數「-g」代表此模組是安裝在系統目錄,讓所有目錄都可以使用。也因為是裝在系統目錄,在OSX環境下需要以管理者權限執行,需加上「sudo」。windows環境下就不需要加sudo。
  • 安裝express-generator之後,切換到想要建立project的目錄,執行「express (project名) -ejs」,express模組就會幫忙建立一個新的目錄,裡面包含基本的http server處理的所有檔案。本文之後都以「<project root>」來描述本文所使用的project的根目錄。
    註:「ejs」是javascript的代碼注入模組,後述。
然後來看看建立了哪些東西:

圖上左側的樹狀檔案列表,就是產生出來的檔案們。
東西很多,來一個個的看。

認識package.json

package.json:為npm的進入點。(npm執行沒有帶「-g」參數,也就是對目前的所在目錄處理的指令,都會參照執行當前目錄下的package.json檔案。)所以先看這檔案的內容:

{
  "name": "untitled",
  "version": "0.0.0",
  "private": true,
  "scripts": {
    "start": "node ./bin/www"
  },
  "dependencies": {
    "body-parser": "~1.18.2",
    "cookie-parser": "~1.4.3",
    "debug": "~2.6.9",
    "ejs": "~2.5.7",
    "express": "~4.15.5",
    "less-middleware": "~2.2.1",
    "morgan": "~1.9.0",
    "serve-favicon": "~2.4.5"
  }
}


在node.js的世界,習慣使用npm start來啟動server端的運行。「start」就是對應到上面的程式碼的"scripts"裡面的"start"。所以下一步就是執行「node ./bin/www」。
當然可以自行加上許多指令。像是test啦,packaging等等...
若是想不經由npm來執行的話,在<project root>執行「node ./bin/www」也可以達到一樣的結果。

"dependencies" 是一大重點。裡面表列的是這個project會用到的所有node.js模組。本文寫到現在,都還沒安裝過模組。上面的模板產生出來的部分,在<project root>執行「npm install」就會全部幫你裝在這個project裡面的「node_modules」目錄下,不會更改到安裝在系統環境下的模組。至於這些模組是不是「必要」,得等到一個個去了解之後才能確定,在此不研究。

要如何增加模組?直接編輯package.json之後再執行「npm install」當然可以。或是執行「npm install <模組名稱> --save 」這樣的加上「--save」參數,這樣再開啟package.json看檔案內容,就會發現安裝過的模組的名字會出現。

至於不使用bower,直接讓前後端所有的模組全部擺在一起會不會有缺點,目前不得而知。先暫時讓它混吧。migrate總是痛苦的。像是模組命名不同,前後端用的版本不同等等瑣碎的問題可能會大量發生。

有了進入點之後,接下來就是依序追蹤。繼續看start參數所指定的執行指令檔:./bin/www

#!/usr/bin/env node

/**
 * Module dependencies.
 */

var app = require('../app');
var debug = require('debug')('untitled:server');
var http = require('http');

/**
 * Get port from environment and store in Express.
 */

var port = normalizePort(process.env.PORT || '3000');
app.set('port', port);

/**
 * Create HTTP server.
 */

var server = http.createServer(app);

/**
 * Listen on provided port, on all network interfaces.
 */

server.listen(port);
server.on('error', onError);
server.on('listening', onListening);

/**
 * Normalize a port into a number, string, or false.
 */

function normalizePort(val) {
  var port = parseInt(val, 10);

  if (isNaN(port)) {
    // named pipe
    return val;
  }

  if (port >= 0) {
    // port number
    return port;
  }

  return false;
}

(....  後面的程式碼略過)

可以看出這檔案讀取了「../app」,也就是「./bin/」的前一個目錄的「app.js」。
(沒指定副檔名是因為node有一個查找的機制。有興趣的話請翻閱其他網站的說明)
跟「http」模組(此為node.js內建)。

然後做了啟動http server的動作,跟listen port。這些都是基本的http server啟動流程。
有了基本的http server的流程,在這邊先來試試產生的模板是不是能正常運作吧。
在<project root>執行「npm start」。要是執行「npm start」發生錯誤的話,應該是沒有先執行「npm install」安裝相關模組。
接著用browser 連線「localhost:3000」...

看來是可以運作。safe~~~
這時可以按下ctrl+c停止server運作,繼續迷航...


認識app.js

上面的兩個檔案所提供的資訊,總覺得好像沒做到什麼設定。需要更多的資料來了解。
http.createServer(app) 這個app參數相當可疑。
總之來看看<project root>的app.js:

var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var lessMiddleware = require('less-middleware');

var index = require('./routes/index');
var users = require('./routes/users');

var app = express();

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');

// uncomment after placing your favicon in /public
//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(lessMiddleware(path.join(__dirname, 'public')));
app.use(express.static(path.join(__dirname, 'public')));

app.use('/', index);
app.use('/users', users);

// catch 404 and forward to error handler
app.use(function(req, res, next) {
  var err = new Error('Not Found');
  err.status = 404;
  next(err);
});

// error handler
app.use(function(err, req, res, next) {
  // set locals, only providing error in development
  res.locals.message = err.message;
  res.locals.error = req.app.get('env') === 'development' ? err : {};

  // render the error page
  res.status(err.status || 500);
  res.render('error');
});

module.exports = app;

喔喔。前面留下來的疑問全部都得到了解答。
標記著顏色的require,剛好呼應了dependencies裡面的定義。
大量的express設定就請參考文件。
重點:
  • 「app.set('view engine', 'ejs');」表示express在render網頁的時候,會加上ejs的處理流程。
  • 「module.exports = app;」定義若是此檔案被require的時候,該回傳的是哪個東東。會回傳的是「app」這個參數所代表的物件,前面有個「var app = express();」的動作,所以這個app也就是代表執行「express()」之後所產生的物件。
  • 「app.use('/', index);」表示若得到的url request的路徑是'/',就會執行index這個動作。

而index是由「require('./routes/index');」所定義。所以我們再看./routes/這目錄下面有沒有「index」相關的檔案。有找到index.js。看看內容:

var express = require('express');
var router = express.Router();

/* GET home page. */
router.get('/', function(req, res, next) {
  res.render('index', { title: 'Express' });
});

module.exports = router;

看起來似乎是在所謂的router裡面加上url的比對跟安裝callback執行比對之後的動作:回傳一個render過的網頁內容。取得views/index.ejs之後,ejs模組依照傳入的參數跟檔案本身的內容做處理,回傳給browser。

有router.get(),當然也有router.post()。就看使用的需求了。
req是browser傳來的request的內容。應該會經由「bodyparser」處理成object跟一個個的參數。
res對server來說就是對browser輸出的介面。除了回傳網頁之外,發送檔案/url redirect都是做得到的。這部分就請參考文件。


導入IDE:webstorm

到這裡,基本的web server的流程介紹完畢。終於可以開始著手撰寫了。
總覺得一直參考來參考去的很麻煩。很需要好用的整合開發環境。
ios有xcode,android有android studio,windows有visual studio, 那javascript呢?

找了一陣子資料,看來目前最強的是webstorm。有30天試用期。試用之後發現真的是沒有它不行... 因為它整合了debug最重要的功能:中斷點。

其實一開始的檔案列表的圖就是webstorm的介面。
來看看webstorm有多方便吧。
從官網下載,安裝完webstorm之後,執行。

選擇「Create new project」,選擇「Empty Project」,避免webstorm可能會自動產生一些東西來改變之前的成果。填入之前建立的project的根目錄,點選「create」:
之後webstorm會提醒此目錄不是空的,是否要以原有的資料來建立project,選擇「Yes」。

然後就進入了主畫面。


設定webstorm的debug環境

接著就來試試要如何debug吧。要是使用的webstorm,右上角的蟲子icon此時是綠色,可以跳過以下設定debug環境的步驟,直接下斷點試試。
若是右上角的蟲子icon此時是灰色,點選右上角的三角形指向下的方塊,選擇「Edit configurations」。

進入run/debug設定畫面。點選左上角的「+」,在浮現框裡面點選「Node.js」。

然後在圖中的藍色框處填入前面有提到的npm start command:「./bin/www」
再選擇右下角的「ok」。

以上的步驟就是讓webstorm在debug的時候去啟動node.js。這樣我們就可以依照之前的連線的經驗去對server連線。應該會發現右上角的綠色三角形跟蟲的符號成為可選狀態。

為什麼debug config不用npm start不就簡單多了?
經過測試,這樣做的話似乎在npm啟動server之後過個幾秒就會停止server,不知原因...

接著如下圖,在index.js的第6行的數字右側點擊,該行就會出現一個紅點,這就是debug的中斷點。再點選視窗右上角的蟲子符號,使用browser連線「localhost:3000」...

有如下圖般的變成藍色的話,代表中斷點正確運作。這時可以按視窗左下角的綠色三角形讓程式繼續跑。

webstorm簡單介紹到此。已經可以滿足基本的開發需求。


前端打包:webpack

接下來想知道的是:前端的開發/模組安裝/打包要怎麼解決?

這部分其實因為在bower還沒被放棄之前,前端開發的javascript模組的管理都是交給它處理。但是現在就得另找方法解決。就算是跟後端的模組混在一起放,那也是得解決之後打包的問題。

ok。既然決定引進打包功能,就要照打包軟體的建議做法來執行。
本文使用webpack做為打包工具。以下是webpack建議的路徑設定:

.
├── package.json
├── public
│   ├── index.html
│   └── js
│       └── bundle.js
├── src
│   └── js
│       ├── app.js
│       └── modules
│           ├── modulea.js
│           └── moduleb.js
└── webpack.config.js


webpack的開發習慣:<project root>/src目錄做為開發用的程式碼放置目錄,
而<project root>/public則是輸出結果用的。<project root>/public目錄,在express-generator幫忙做出來的檔案裡面已經有了,剛好不需因路徑的更動而改動改太多程式碼。
當然,一鍵做完所有處理之後還可以debug,是必須達成的目標。

總之先把webpack/jquery/angular/bootstrap裝好。
也裝裝webpack在本文裡面會用到的extract-text-webpack-plugin/ css-loader / style-loader / url-loader:
npm install webpack --save
npm install angular --save
npm install bootstrap --save
npm install extract-text-webpack-plugin --save
npm install css-loader --save
npm install style-loader --save
npm install url-loader --save

npm有個package.json為進入點,webpack當然也有個設定檔。就是「webpack.config.js」。
因為不像express有建立模板的工具可用,參考其他網站的設定,在<project root>建立檔案「webpack.config.js」:



// 有套件需要絕對路徑的設定,導入path模組。
var webpack = require('webpack');
var path = require('path');
var ExtractTextPlugin = require('extract-text-webpack-plugin');

var plugins = [ new webpack.ProvidePlugin({
    $: 'jquery',
    jQuery: 'jquery',
    //'window.jQuery': 'jquery'
    })
    , new ExtractTextPlugin('stylesheets/[name].bundle.css') ];
// webpack.ProvidePlugin是為了讓webpack可以包入jquery而使用的。webpack內建支援,不需另行安裝模組。
//ExtractTextPlugin是為了讓webpack把css不內包在.js,另存一個檔案用的。聽起來有點畫蛇添足?因為把css獨立出來的好處是讓html可以同時讀入js跟css。一次只同時讀一個css跟一個js是目前比較推薦的設計。
//預設路徑是output的path。


module.exports = {
    // 進入點。別跟<project root>/app.js搞混。這個是給前端用的。可以有多組。
    entry: {
        app: './src/js/app.js',
    },
    // 檔案輸出設定
    output: {
        // 輸出檔案名。
        filename: 'js/[name].bundle.js',
        // 輸出路徑。webpack v2以後需要指定絕對路徑。
        path: path.join(__dirname, 'public')
    },
    plugins: plugins,
    devtool: 'source-map',  //輸出code map,讓debug tool可以斷點。
    resolve: {
        modules: [ path.join(__dirname, "node_modules") ],
        extensions: ['.js', '.css']
    }, 
    module: {
        loaders: [
            // loads css
            { test: /\.css$/, loader: ExtractTextPlugin.extract({
                fallback: 'style-loader',
                use: 'css-loader'
                })
            },
            { test: /\.svg(\?v=\d+\.\d+\.\d+)?$/, loader: 'url-loader?mimetype=image/svg+xml' },
            { test: /\.woff(\d+)?(\?v=\d+\.\d+\.\d+)?$/, loader: 'url-loader?mimetype=application/font-woff' },
            { test: /\.eot(\?v=\d+\.\d+\.\d+)?$/, loader: 'url-loader?mimetype=application/font-woff' },
            { test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/, loader: 'url-loader?mimetype=application/font-woff' }
        ]
    }
};

註:
  • [name]為webpack的專用指令。會自動帶入entry的參數名。
  • plugins:指定需導入的plugin。已定義在前面...
  • resolve:指定「require」或是「import」指令該到哪裡找資料。因為我們沒有把前端跟server端所使用的模組拆開放,目前只要指定npm安裝過的模組的安裝目錄「node_modules」即可。 
  • module:指定讀入該模組之後該做怎樣的處理。test會把讀入的檔名以「正規表示法」的方式比對看看是否符合。符合的話就以此條件的指定loader處理。第一個條件是副檔名為.css,loader是ExtractTextPlugin。ExtractTextPlugin將會以套入的參數設定:先使用css-loader,若是loader報告無法處理的話,再使用style-loader處理。目前這是為了bootstrap必須被含入的「bootstrap/dist/css/bootstrap.css」的設定。有興趣把bootstrap.css從sass層次解譯之後還含入的話就自行多試試吧。
  • 因為bootstrap裡面有不少圖檔資源必須含入,所以下面含入了.svg/.woff/.eof/.ttf檔案的處理。使用「url-loader」做處理。


接著準備src/js/app.js,webpack會幫忙把相關會用到的.js全部包在一起。
包含之後測試angular的controller程式碼。

// style library
require("bootstrap/dist/css/bootstrap.css");
require("bootstrap/dist/css/bootstrap-theme.css");

// javascript library
var $ = require("jquery");
var angular = require("angular");
require("bootstrap/dist/js/bootstrap.js");  //bootstrap的功能

// angular module
require("./angular/controller");





為了方便測試webpack的處理,我們在package.json裡面的script多加一個build的指令去call web pack。到這裡,檔案結構大概是這樣:


然後就可以執行「npm run build」來執行webpack了。(非npm內建的關鍵字,都要加上「run」來告訴npm後面的指令是要到package.json的scripts裡面找。)
webpack執行結果:

看起來是沒問題。(實際上為了測出這樣的參數,已經錯了不下百次)
那就來準備基本的測試頁來試看看嘍。


前端開發

以下的頁面將會有一個輸入框跟顯示區來測試angular的雙向資料綁定,跟bootstrap的著色提示框。別忘了目前的開發環境,html檔是views目錄下的「index.ejs」。(請參考前面的檔案結構列表)

修改views/index.ejs 如下:
<!DOCTYPE html>
<html>
  <head>
    <title><%= title %></title>
    <link rel='stylesheet' href='stylesheets/app.bundle.css' />
    <script type="text/javascript" src="js/app.bundle.js" />
    <!--要含入的資料,會是經過webpack輸出的結果。-->
  </head>
  <body>
    <h1><%= title %></h1>
    <p>Welcome to <%= title %></p>

    <div class="alert alert-warning alert-dismissible show" role="alert">
      This is Bootstrap....
      <button type="button" class="close" data-dismiss="alert" aria-label="Close">
        <span aria-hidden="true">&times;</span>
      </button>
    </div>

    <!-- angular data binding test -->
    <div ng-app="app"  ng-cloak>
      <div ng-controller="helloCtrl" ng-init="init()">
        <input type="text" ng-model="demo">
        <div>{{ demo }} </div>
      </div>
    </div>
    </body>
</html>


修改src/js/angular/module.js 如下:
module.exports.angApp = angular.module("app", []);


修改src/js/angular/controller.js 如下:
let mHello = require('./module');

mHello.angApp.controller("helloCtrl", ['$scope', "$log", function($scope, $log) {
    $scope.init = function() {
        $log.debug('Hello Angular');
        $scope.demo = 'Hello Angular';
    };
}]);


使用browser連線localhost:3000之後的顯示結果:

輸入框裡面的文字修改之後,下方的字會跟著變化,黃色提示框右邊的X點選之後,提示會消失,應該是會動了。



Webpack的殺手應用:動態編譯

最後一步:build兼啟動server。經過一陣子的收集資料,發現webpack可以動態編譯,不過大部分都是靠webpack-dev-server的cli來達成。本文從原本的express的基底,加上webpack-dev-server,靠webpack-dev-server的動態編譯來達到改code免重新啟動debug。

需安裝的套件:
webpack-dev-server / webpack-dev-middleware / webpack-hot-middleware
npm install webpack-dev-server --save
npm install webpack-dev-middleware --save
npm install webpack-hot-middleware --save

修改<project root>/app.js...
把程式碼的20行以後到註解「// catch 404 and forward to error handler」
的部分修改如下:
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(lessMiddleware(path.join(__dirname, 'public')));

app.use('/', index);
app.use('/users', users);
   
if (process.env.NODE_ENV !== 'production') {  //只有開發模式才這樣用。
    const webpack = require('webpack');
    const webpackDevMiddleware = require('webpack-dev-middleware');
    const webpackHotMiddleware = require('webpack-hot-middleware');
    const config = require('./webpack.config.js');
    const compiler = webpack(config);

    app.use(webpackHotMiddleware(compiler));
    app.use(webpackDevMiddleware(compiler, {
        publicPath: "/",
    }));  //publicPath: 指定輸出的路徑是server url的根目錄開始。因為webpackDevMiddleware的所有資料是在記憶體中處理。
}
else  {
    //express-generator做出來的這個設定會導致動態編譯失效,讓它在非開發模式執行。
    app.use(express.static(path.join(__dirname, 'public')));
}

// catch 404 and forward to error handler

啟動webstorm的debug,從webstorm的console確認compile成功之後,使用browser連線「localhost:3000」,看看會不會有網頁出現。
成功的話,可以開始修改controller.js或是index.ejs或是自訂的css,然後reload browser,看看會不會更動,體驗免編譯開發。


以上。

2017年11月28日火曜日

[禁止酒駕]Whisky Luxe 2017


這個活動其實在第二屆有參加過。但是那次的參展陣容覺得有點少,之後被嚇到不敢參加。今年看了一下廣告,似乎免費喝的款式多了不少,於是就決定再參加一次。


很高興的是,今年的確沒讓我失望。完全是值回票價的一場品飲會。
雖然側邊的攤位跟首次參加的印象一樣,通道只容得下兩人行走真的是太擠... 只要有人在攤位前就難以移動。覺得這場地鐵定要換的。

有了上次的經驗,這次也學乖,提早兩小時去排隊,順利的擠進前30名。
不過因為開場衝去排輕井澤之後被帶到錯誤的隊列,再回去已經來不及,於是放棄。
反正現在已經是貴到買不起的酒

下面這幾張是摸不起的超高價。看看就好...




這次想排的第一順位是山崎的水楢桶。在輕井澤排失敗之後就直接去suntory攤位。
感想:非常強的花香。蜂蜜,太妃糖,木香,淡煙燻,帶著白醋味。的確是不錯喝。不過在日威價格不合理的時代,有體驗過就好。

圖中這隻山崎50y要價600K。



籌碼換來的kingsburry,覺得普通。硫,碘,橡膠,微嗆。


沒想到的是本屆個人MVP在喝第三隻的時候就出現了。就是圖中這款。
碘,煙燻/烘烤木桶,木香,堅果味。強烈的稻草煙燻味,有如置身在燒稻草的濃煙裡面。

接著有排到麥卡倫紫鑽。也是一隻被炒得恨天高的酒(行情約5K)。喝過只覺得還好。陳年蘭姆酒風,微澀...


愛爾蘭威, 覺得比較像穀物威士忌的味道。花香,糖香。

繞到台酒攤位,有風味桶原酒可以付費試飲。為了滿自己的好奇心,於是就買了杯梅子桶試試。喝完的感想:對風味桶死心了XD  不過也可能是被前面幾隻超級好酒給洗過,影響判斷... 之後還是會給它機會。


一系列藍姆酒。自然是每一隻都要給他喝過。
barbados 2012, 甘甜,草香。
panama 2010, 香氣比較沒那麼明顯。
guadeloupe 2013 香草。

下面這兩支有覺得比較好。尤其是圭亞那的非常棒。甘甜,不錯的香草味,香瓜味,還帶了淡淡梅子味。
fiji , 清香,微甘。

蠻有趣的一款威士忌。 有著清酒的味道。

Benrinnes 21y,草香,糖香,橡膠,奶油,微甘,澀。

CLYNELISH 20y,沒試過的酒廠。果香,橡膠味。

spey給了四款市面看得到的試飲。這時味覺已經差不多不行了。
spey 1999:53.8,果香,烏梅。

spey tenne aged ,花香,微甘,烏梅
spey byron,花香,清香,柑橘,入口後的刺激感較強。

中場休息30分鐘,喝水吃零食順便醒醒酒... 喝酒的場子不應該出現會影響味覺判斷的東西(身上不可帶香水),所以場地內沒有飲食攤。加上很容易餓,自己帶些零食是強烈建議選項。


接著轉到一開始被輕井澤擠爆的華緯國際,這次帶了非常多隻酒,一攤就可以讓你喝到掛。
這隻鳳梨GIN有成熟鳳梨味跟煙燻味,草味帶有一絲絲,提醒著它是GIN...
還有另一隻櫻桃GIN,就很明顯的有草味,比較喜歡這隻的平衡度。

Oc3這隻可以免費試飲,也試了一下。看到60%就忍不住
跟左邊的個人單場MVP比,也有不錯的煙燻味,不過尾韻的甘甜就是MVP較少的。

後面的因為不勝酒力就沒喝了。拍拍瓶子...












看到以上的圖就可以了解,這次的免費喝的陣容的確是夠多夠精彩。
場內下排左側的攤位都還沒注意到,就到了散場的時刻。以後都這陣容的話就會場場報到了。

2017年7月14日金曜日

[安藤]android studio 2.3 with JNI(使用CMake做為編譯工具)

原來android studio 2.2之後就可以不用靠gradle-experimantal來支援native api,
於是趕快來試看看。畢竟gradle-experimantal用起來總是毛毛的。

前置準備:
  • 使用sdk manager安裝cmake。(選擇「sdk tools的tab就可以看到」)
然後在main project的build.gradle裡面增加下面紅色的部分:

android {

    compileSdkVersion 24    buildToolsVersion "25.0.2"    defaultConfig {
    ...
    }

    productFlavors {
    ...
    }

    externalNativeBuild {
        cmake {
            path 'src/main/cpp/CMakeLists.txt'        }
    }
}
 
要注意的是CMakeLists.txt的路徑。上面的例子是放在[main project]/main/cpp 裡面。
(cpp目錄不存在的話請自行新增) 
當然也可以放在其他地方。最建議的位置是[main project]的根目錄。
另外,同一個module的CMakeLists.txt只能有一個。要含入其他的navive c 的lib的話都要寫在這個唯一的檔案裡面。

再建立一個JNIClass.cpp(檔名隨意),放在路徑[main project]/main/cpp。


CMakeLists.txt的內容:
 
# Sets the minimum version of CMake required to build your native library.
# This ensures that a certain set of CMake features is available to
# your build.

cmake_minimum_required(VERSION 3.4.1)

# Specifies a library name, specifies whether the library is STATIC or
# SHARED, and provides relative paths to the source code. You can
# define multiple libraries by adding multiple add.library() commands,
# and CMake builds them for you. When you build your app, Gradle
# automatically packages shared libraries with your APK.

add_library( # Specifies the name of the library.
             app  # build出來的lib的名稱。
             # Sets the library as a shared library.
             SHARED

             # Provides a relative path to your source file(s).
             JNIClass.cpp  #所有c/c++檔案的列表。此例的c檔案跟CMakeLists.txt放在同一個目錄,所以可以不指定檔案路徑。若是不同路徑的話請自行指定。
)

# log
find_library(log-lib log)  # 有要include各種android os系統內建lib的話可以用這方法找。請注意對應的顏色。
target_link_libraries(app ${log-lib} android)  # 需要include的各種lib。似乎是要包含自己。
# Specifies a path to native header files.
# include_directories(src/main/cpp/) # 要增加其他的原始碼所在目錄的話可以用此法。



之後重新sync project再run /debug project應該就可以了。







2017年6月18日日曜日

[PS4]Let it die 無課金登頂感想,給打算開玩的人的建議

登頂證明。這款遊戲在日本是CERO Z分級。筆者在被Dark souls系列的對戰空氣劍砍到一肚子火之後,對這款無連線對戰型的動作遊戲發生興趣,但是在購買日版的時候遇到阻礙。因為CERO Z的遊戲網購的話需要刷信用卡。但是PSN 日版帳號不給刷海外信用卡,手上也沒JCB系統的信用卡。在打算放棄的同時,發現亞洲版是連錢都不用花就可以直接下載,而且語系可以切換成日文,語音也可以切換成日語(聽不到高橋名人跟天龍源一郎的聲音,想玩的動力會少一半),就開玩了。
寫本篇的用意是讓想玩的各位可以少走冤枉路真正的穩死不再拖

玩家操作的角色是「戰士」,為了登頂的獎賞而努力。
在操作教學跟劇情交代結束之後,到了所謂的「候車室」。
遊戲場景的塑造,筆者相當喜歡。對日本鐵路有認識,看到這頹廢感滿點的場景就可以想像一陣。不過在一開始的時候也只是個造景,並無用途。

一開始什麼都沒有,也沒錢買武器跟裝備,只能直接出門。在不熟悉敵人的習慣的時候很快就死了。這時瀬戸際子第一次登場,介紹保險:付一顆Death Metal(在無料課金遊戲裡的通俗稱呼叫做石頭,之後本文也都使用這稱呼)就可以復活。

畢竟這是課金遊戲。會故意設計成比Dark souls更不合理的難度也是無可厚非。
但是無課玩家怎麼可以就這樣屈服?目標就是一顆也不繳出去啊啊啊!
石頭對無課玩家來說只有一個用途,就是增加倉庫空間。
本遊戲運營送的石頭非常少。就算是不買保險,全部拿去增加倉庫空間也還是加不滿。 


剛開始還不算太難,常玩這類遊戲的人應該還不至於會一直死。
打到第三層樓,出現第一隻BOSS。大約試了三到四次過。(有朋友玩到這BOSS就放棄了)
因為初期是故意設計成讓玩家必須靠撿敵人裝備生存。因為寶箱內的設計圖出現機率低。
(不過有部分寶箱的設計圖出現機率高,習慣地毯式搜索的玩家可能會覺得還好。)
加上死掉之後,戰士會留在當地成為死屍,要救回只有兩個方法:到該樓層殺掉它(戰士身上的物品跟獲得的金錢靈魂全部消失)或是到候車室的戰士冷凍櫃花錢救(所有物品保留)。戰士只有一隻死掉怎麼辦?本遊戲的貼心(?)設計是買等級1的戰士免錢。一開始冷凍櫃也有給三個空間(可以靠靈魂擴充)。

戰士的區分方式:
  • 6大參數:除了攻防的數值之外,主要的影響是武器防具的裝備限制。
    HP:應該不用贅述。
    STR:攻擊力。基本上打BOSS都是靠香菇疊參數短期決戰(裝備消耗型遊戲的宿命),拖越久越不利(裝備一壞就是死連換裝備的時間都沒有),筆者認為是本作最重要的參數。
    STM:持續力。數值越大,執行除了走步跟防禦以外的動作的時候的心臟跳動加速度越慢。為初期最重要的參數。完全沒加的狀態,只要翻滾三次就會在原地喘,等著被打。
    DEX:技巧。會影響遠距攻擊武器的威力。
    VIT:體力。會影響防禦力。依目前版本的經驗來看,到遊戲後期都只能靠裝備補強。到後期重要性大減的參數。
    LUK:運氣。除了暴擊率(傷害為1.5倍)大增之外,只有感覺到對遠征的掉寶量有影響。
  • 分級(Grade)。Grade目前是1~5,6月底的大改版將會加入Grade 6。
    分級之間的差異很大。可以想成後一級的全滿參數,是前一級的等級全滿的參數的兩倍。加上戰士的開放購買條件是以實際到達過的最高樓層決定,所以本遊戲的戰略之一:能夠往上爬就往上爬。

  • 種類:參數上限值的差異。
    • 全能型:參數平均。一般建議是不知道該選哪種就用這種,但是筆者覺得對攻略來說一點也不好用...
    • 近接型(Striker):HP跟STR為最高值。DEX最低所以本作目前最強的武器:刺劍必須靠貼紙降低裝備限制才能用。然後用了之後就成為最強攻略用戰士...
    • 防禦型(Defender):VIT跟HP為最高值。會明顯感覺到防禦力是有比較高。第一次打boss好用。但是武器請帶夠。要不然通常是武器先用光。
    • 攻擊型(Attacker):STR跟DEX為最高值,但是HP只有一般型的一半。筆者認為不適合攻略用。太容易死了... 若是拿來防禦襲擊,配上遠距離武器就很難纏。
    • 遠距型(Shooter):DEX為最高值。沒拿槍活不下去。近距離武器的攻擊力相當慘...
    • 挖寶型(Collector):身上可攜帶的物品量(裝備空格)是其他類型的兩倍。需要大量收集素材的話,可以少回幾趟候車室。據說6月底大改版的Grade 6可能會大減裝備空格,也許這型的會在攻頂之後大放異彩。
    • 貼紙型(Skill Master):身上可以貼的貼紙量是其他類型的兩倍。假如轉蛋轉到很多夠強的貼紙的話就練一隻吧。
    • 幸運星(Lucky Star):LUK為最大值。加滿的話除了暴擊機率大增之外,遠征的掉寶量會是其他類型的1~2倍。
     
  • 戰士的開放購買條件是突破的樓層決定:

    Grade 1Grade 2Grade 3Grade 4Grade 5
    全能型一開始11F到達16F到達25F到達35F到達
    近接型6F到達11F到達16F到達25F到達35F到達
    防禦型8F到達12F到達18F到達25F到達35F到達
    攻擊型8F到達12F到達18F到達25F到達35F到達
    遠距型6F到達11F到達18F到達25F到達35F到達
    挖寶型6F到達11F到達16F到達25F到達35F到達
    貼紙型9F到達13F到達19F到達25F到達35F到達
    幸運星       9F到達13F到達19F到達25F到達35F到達
      
Grade 3。
Grade 4
Grade 5。請注意參數的差異。

戰士取得的戰略:建議到6F之後換成近接型。因為6F的BOSS是遠距攻擊型,自己可以躲在障礙物後面,在它瞬移接近你的時候硬敲短期決戰。
到達11F之後馬上回家買Grade 2,登16F之後馬上買Grade 3。
23F的BOSS是中期的一個困難點,建議先不要用Grade 3硬打,請參考此攻略網頁,等到可以從左側旁路上25F的地圖結構出現的日子,從左側先上25F然後買Grade 4。 玩這遊戲切記不要急。急就中了運營的課金圈套了。XD
同樣的,32F的BOSS也是大難關。所以先放置,一樣參考攻略,等到可以從右側上35F的地圖出現的日子,直接衝到高樓,先取得購買Grade 5戰士的條件之後買下來練功之後再攻略就會輕鬆很多。用Grade 4戰士攻略會難到讓你想摔搖桿。就算是有該時期最好的防具,也捱不過3~5次攻擊(尤其30F之後死掉都要花接近20萬的錢才能救,除非挖到非救不可的珍貴物品,通常是直接去殺掉)

筆者只用Striker從頭打到尾。也只建議用它。主要是高攻擊力可以省去裝備消耗,HP也是最多,比較不容易死。比較一下Striker跟Attacker,以裝備限制為STR/LUK的近距離武器來比,傷害數字的差異只有10%。換成裝備限制為DEX的遠距武器或是刺劍/武士刀來比較,傷害差會拉到30%。至於HP少到只有三分之一的高風險是不是能接受就看自己了。

本遊戲的基本戰術:
  • 攻擊後出:這遊戲揮空的代價太大。除了攻擊距離夠遠的槍(用子彈的跟桿子夠長的都算)跟攻速夠快的刺劍之外都不建議先出。
  • 儘量一對一:這太基本應該不用贅述。
  • 利用敵人的攻擊:敵人的攻擊「會」波及其它敵人。
  • R3鈕下壓可以鎖定敵人:但是缺點會變成後退速度不夠。初期不習慣攻擊的時候或是使用攻擊範圍窄的刺劍的時候可以鎖定,攻擊範圍較寬的武器都不建議鎖定。這遊戲在不鎖定的狀態下還是有一定的自動導向攻擊範圍。
  • 背對敵人的時候,敵人會積極的攻擊:遇到愛防守或是後退的敵人就用這方法引誘攻擊。要注意的是啟動R3鎖定,在一對一的情況下就不會讓敵人看到背了...

冷藏庫買滿了,所有的戰士全死了怎麼辦?砍掉再買嘍。不過要是會玩到全死這地步的話,筆者覺得也不用玩下去了...因為太痛苦。
3F的BOSS算是第一個判斷要不要繼續玩下去的評估點。
因為當一隻等級練滿,身上裝備滿滿的戰士死掉的時候,要用等級1而且裝備不足的另一隻去救,相當麻煩。若是購買了新的戰士,建議暫時放置死掉的那隻先練新的這隻。等到練得差不多再去挑戰。這遊戲Grade1~4的等級都還算好練。Grade 5就比較累了...
基本上至少要擁有兩隻同等級的戰士才能互救。




打過3F的BOSS之後,候車室多了一個新功能:東京死神地鐵(Tokyo Death Metro,簡稱TDM)



主要功能:

  • 加強候車室的設備
  • 襲擊別人的候車室(去別人家還得花錢買車票的意思)。襲擊成功(擊破防守側的戰士或是錢箱魂箱,破壞率超過50%)可以獲得防守側目前擁有的十分之一的錢跟魂。
  • 設定防衛用的戰士:要注意的是裝備若是無法自製的,被AI使用之後耐久度不會恢復。若是戰士被擄走,裝備格子內的物品會全部消失,被擄走超過48小時,戰士就會變成對方的。要救回來有四個方法:再襲擊對方搶人,花錢贖回,等別人襲擊營救,襲擊側放人。

    但是襲擊的設計有一條規則,就是「自己待在候車室的狀態下不會被襲擊」。所以擄到戰士之後,對方開機持續連網待在候車室兩天,除了付錢之外沒其他方法可以救。這是筆者因此暫停遊玩此遊戲的原因。因為被擄了一人走...聽說6月底的大改版會有調整,到時再看情況。
搭車去別人的候車室

這是之前TDM防守的強度評分可以降低的時候踩到雷而拍的圖。
這狀態代表對方的配置戰士高1個Grade以上。基本上是沒啥可能打贏只能逃到底...
方法:擺設高Grade然後等級只有1的戰士防守。 低等級的人看到等級低然後襲擊獎賞很多的時候就踩進去,然後...
現在除非自己選高等級,要不然看不到了。


啟動TDM之後,因為有所謂的「抗爭」的設計,需要加入一個陣營。一般的建議是加入自己的所在地或是出身國。目前陣營的設計是台港澳,日本的47個都道府縣,美國的每一個州,跟其他國家。加入陣營的優缺點分析:
  • 加入人多的:容易發生抗爭,被襲擊的可能性也增加。好處是只要在抗爭狀態去襲擊一次抗爭對象,在抗爭結束(24小時)之後不管抗爭輸贏都可以獲得獎賞。
    襲擊對象的強度影響積分差異不多(最多20%),打越多次越賺就對了。之前參加的時候打約10場就可以搶到前15%,可以賺到一顆死神金屬跟22000的錢與魂。對攻略來說是非常大的好處(別忘了這是個為了要你課金非常缺錢的遊戲)。而且獲得的錢與魂不是馬上入手,而是存在置物箱,這樣可以讓手上有的錢與魂儘量少,減少別人襲擊的意願。有需要用的時候再領出來馬上用掉。

    引用一下06/16 E3 2017會場直播的圖:
    加州爆量不知原因...可能本來就人多。聽說遊戲剛開始的時期,只有加州可以襲擊運營TEAM(一種搖錢樹的感覺)
    總之筆者只建議加入人多的。
     
  • 加入人少的:被襲擊的可能性少。抗爭的觸發頻率低,抗爭勝率高。(這邊牽扯到襲擊的裏設定:個人不會持續被襲擊。估計約一小時才會被襲擊一次。所以人少的陣營從人多的一方來看,常常會找不到對象可以打。反過來說,人多的陣營就會一直被狂打)


到此算是真正的遊戲開始。



遊戲的目的是登頂。關卡以一個個的有限區域構成,以樓層代表難度的提升。
地圖(樓層與區域)的構成方式日本時間每天09:00會更換。說是會變化也還不到完全亂數。(畢竟有單行道或是有條件開放的設計)。目前確定的是固定四種方式。
每10階層為一個主題,也是難度的分界點。每3跟6階會有中BOSS,每10階有一隻大Boss。
各關卡的寶箱跟素材還有敵人的配置,是以預先定義的固定位置,
加上亂數來決定會不會出現素材,會不會出現寶箱,與寶箱的內容。
本作的物品:
  • 死神金屬(Death Metal) :把它想成課金石就對了。
    取得方式:目前運營每週送一顆,用現實通貨買(每10顆約台幣$140),完成遊戲中的任務,在區域對抗襲擊別人的候車室
  • 錢:為最重要的物品。
    取得方式:打敵人,襲擊別人的候車室,課金。
    買裝備(本作的裝備會持續消耗)要錢,戰士死掉救回要錢,買高等級戰士要錢,買貼紙要錢,錢還會被搶。
  • 魂:主要用在候車室的設施跟裝備開發。初期應該不會不夠用。到裝備開發一次會吃掉8000以上的魂的時候就會開始擔心了。
    取得方式:打怪,打別人死在當地的戰士(給的量蠻多),襲擊(取得量的多少,襲擊之前有提供數值參考)。
  • 裝備設計圖:取得之後送回候車室的商店,以後湊滿素材就可以耗用靈魂值來開發武器。開發完之後用錢買。
  • 素材:讓裝備設計圖成為可購買的裝備的物品。
    為本作的第二個是否要玩的考量點:素材取得地獄。
    因為本作的裝備升級困難與麻煩度,跟一般的OLG有得拚。
    素材的分類(製作裝備的設計圖會用到):
    • 一般素材:鐵/鋁/銅/木板/布/油 (散落各處,有的區域會限定只掉某一類的。每一種再細分為五級。)
    • 絹(布系第五級)目前玩到登頂都還沒用過。建議先留個幾塊就好。
    • 打機器系的敵人會掉的素材:Rare Metal(每一種敵人會掉一種。掉的機率似乎跟敵人強度無關)
    • 打Boss會掉的素材:目前分成五級。
      • COEN:D.O.D系
      • JIN-DIE:War Ensenble系
      • GOTO-9:Candle wolf系
      • U-10:M.I.L.K系
      • Boss會掉的素材,大寶箱也會掉。請參考攻略會提到的大寶箱的位置。筆者常用的大寶箱區域:18F的TEMO-UMA,22F的KAWABE,32F的KOSHI-YAMA。
       
    素材地獄發生在遊戲中期(20F~30F)。這個階段出現本作最強武器:帶電刺劍。攻速快,以當時的防具擋不住,被擊中會因為電擊效果硬直,沒有閃躲的機會,只要中一劍通常是7連擊全吃,防具不夠通常是即死。要克服刺劍的第一步自然是擁有刺劍,所以需要先取得關鍵素材。
    刺劍強化要求的關鍵素材,是「黑色M.I.L.K稀有素材」,這東東所有的中BOSS都不會掉,只能靠重複開20F~30F的大寶箱取得。加上大寶箱會出現的東西也不是只有稀有素材,整個機率算起來可能只有10%,因此筆者連續跑了近百次的22F KAWABE才把刺劍升級到堪用的程度...
    當然也可以先練習如何克服刺劍,因為這武器的攻速快所以只要一看到動作就可以擋兼彈劍,不過風險非常高,練習到會,可能已經不知死了幾次。
  • 裝備:取得方式為在候車室的商店買,打敵人掉落,寶箱內容。裝備升級靠取得素材跟靈魂。裝備的設計概念跟樓層的主題有關。

    1f~10f:D.O.D ,「Do it self Or Fucking Die!」 的縮寫。 武器跟裝備的設計都比較偏DIY工具系。像是鐵鎚,蒸氣熨斗,十字鎬,電鋸,釘槍,肉刀,圍裙,工地帽,鴨嘴帽等等。
    11f~20f:War Ensenble,軍用系。所以武器裝備的設計偏槍,砲,蝴蝶刀,柴刀,防彈衣,迷彩服。
    21f~30f:Candle wolf,中世紀幻想系。武器裝備有武士刀,爪,長劍,刺劍,斧,牧師袍等等。
    31f~40f:M.I.L.K,運動系。這系列的武器發想就有趣很多。手提機車,發球機,球棒,保齡球...防具像是棒球帽,曲棍球裝,棒球裝也有。

    裝備的強化建議:要用的強化就好。
    武器:
    1~10F建議練最好用的鐵槌。
    11~20F最好用的是柴刀,
    21~30F是刺劍。23F打不過的時候可以考慮強化斧頭,它的必殺攻擊不會被中斷。手提機車雖然一般攻擊不好用,但是必殺攻擊可以用很多次,而且使用的時候無敵,有效時間長,使用一次可以多次打擊,打Boss的時候容易硬過。
    31~40F是噴火熨斗/刺劍/切肉刀。噴火熨斗因為一發是多次攻擊,拆防具背常好用。切肉刀的攻速極快,不輸刺劍。

    防具更是只抓重點強化就好。要不然再多素材都不夠用。而且現在開放第四階段升級,第四階段的素材需求更是誇張...
    建議的是D.O.D的Tracker系列。因為目前開放到第四級,是唯一可以比較輕鬆升級到高等級的防具系列。在那之前比較好升級的有Candle Wolf的Priest衣服(因為稀有素材只要刷11F的Boss即可),M.I.L.K Slugger系列的褲子(第三階段比較容易升上去,而且初期的數值就高)。
  • 香菇:瞬時或是暫時效果的物品。 有攻擊,補血,攻擊防禦力增減,火電毒屬性傷害,無敵透明慢動作等等。
  • 動物: 散落在各個區域。可以抓起來吃掉補血或是殺掉(會在生物體外長出香菇)
  • 貼紙: 裝備在戰士身上的長效物品。 有直接買或是換來的一次性使用貼紙(效果持續到戰士死了之後被自己殺掉),可以重複貼的無限使用貼紙。

    無限使用貼紙以機率的方式取得,當成是轉蛋系統即可。不過是用遊戲中的錢來轉。(對課金玩家來說反而麻煩?)無課玩家初期建議多轉點蛋...要不然貼紙的消耗會是一個問題。
這張貼紙極貴重。有了它,存活機率大增。





1~10F其實還好。有鐵槌就贏了... 10F的BOSS前面有一段路需要走就是。BOSS就靠必殺攻擊狂放吧。
11~20F遇到比較難的地方是16F的BOSS。這BOSS的所在地圖有高度落差,在體力不足的時候會移動到低處,在向下移動的時候會被單方面導彈攻擊,只要中了一發會硬直,然後高機率會連中五發,然後就死了。這BOSS用遠距武器也無法有效傷害,算是初期偏難的地方。20F更是加強版,在這邊死了不少次。

遊戲中期(20~30F)的敵人拿的武器不夠力,撿來也不好用,只能靠自己的武器升級才能強化。這時之前提到的素材地獄就來了。裝備有升級到當時的上限的話,BOSS就靠手持機車+屬性攻擊無效香菇輾過去吧...

後期(31~40F)的第一個難關是32F的新BOSS。弱點是用斬屬性的武器針對尾巴攻擊。總之在有右邊旁路可以上35F的日子先打過這隻BOSS,然後衝到35F,買到Grade 5的戰士,完成可以獲得紅色D.O.D稀有素材的任務,然後升級熨斗為噴火熨斗。這噴火熨斗接下來會陪你到攻頂。
筆者是在運營在某次更新之後出現系統問題,運營決定到下一次更新之前,死亡救回都不用付錢,而且打天龍源一郎的時候還是靠不小心撿來的第四階段武器登頂的。(最終Boss也死了近10次)
要是運營沒有出包的話,筆者早就放棄這遊戲...
在遊戲初期就登頂的玩家真的太神(太會課金?)...

這遊戲目前的問題點:
  • 30F以上的死亡代價實在是太高了。錢光是花在買裝備上面就已經吃不消,還好有找到賺錢的方法,就是在1F找個可以快速來回殺運營角色的區域結構,持續在2F跟1F之間來回。約2分鐘來回一次,在Grade 5的戰士拿到之後,大約每30分鐘可以賺10萬。(其它Grade沒試過差多少錢)不過也只是消耗時間...
  • 裝備消耗速度過快。(大概也是逼玩家課金而設計的)
    使用武器或是防具被攻擊都會導致耐久度下降,而且連裝備的參數都會下降。消耗慢的武器大約可以用個60次,消耗快的40次就壞了... 以子彈計算的槍,除了機關槍有180發,狙擊槍只有16發,EVENT新開發的武器火箭筒更是慘到只有4發。
    在11~20F相當好用的釘槍是有100發,不過後期攻擊力不足。
    防具的話也因為消耗快的這個設計,後期面對裝備太好的敵人,就是靠噴火熨斗快速拆對方防具,要不然很難贏...
    重點:買裝備除了花錢之外,續買同一裝備還要等一段時間。然後要課金才能馬上續買。
  • 後期沒武器防具根本就是死路一條。課金雖然是可以復活,但是裝備不會復活,在裝備全毀之後其實復活了也沒用。赤手空拳面對天龍源一郎,會讓你根本就不想玩...想要像Dark Souls那樣初期狀態打贏必死的橋段?別傻了...攻擊方式速度跟範圍差異不能比...
  • 素材地獄。已經提太多了...
  • 順便拿點剛出爐的E3 2017會場資料檢討會來提提。
    被襲擊側因為戰士的AI太笨,只能靠強力的防具跟難纏的武器。但是這些都比不上暈眩/無敵香菇可以解決所有問題。不過AI太強又會變成襲擊側無解,所以襲擊的調整筆者覺得會是一個大課題。現在大部分的玩者處於別放太多錢在身上的狀態XD




  • 高等玩家可以襲擊低等玩家。筆者現在也這樣...要不然被高等防守打趴一次就襲擊參加不能,損失太大。
  • 目前的襲擊排名的分數第一名,以目前的遊戲規則永遠也無法達成。
    所以運營決定要全部重來了ww



  • 讓筆者暫停此遊戲的原因也是有人提到。既然有拿出來提應該是打算改。

看完了這些,還打算玩的人,上吧。相信你可以玩得很爽。或許大改版會翻盤也說不定。這也是運營型遊戲的好處...吧?

值得一提的是,本作有多個樂團提供的近百首歌曲,要是岀OST至少要5張CD,多到聽不完。而且設計成類似廣播電台的感覺。有DJ的講話跟亂數持續播放,當成背景音樂還不錯。

寫到這邊的感想: