基于HTML5+WebSocket+JAVA的棋牌游戲開發(fā),從入門到放棄(五)

前言

最近有些突發(fā)的事情,在飛機(jī)上寫了點(diǎn)代碼,先把它們更新上來(lái)吧。畢竟這個(gè)文章是做這個(gè)東西的一個(gè)心路歷程,可能有些東西講得并不是很明白。大家可以自己查下資料或者在下面留言。這段時(shí)間,我主要是做了一些前端的的樣式以及“準(zhǔn)備”這個(gè)功能的開發(fā),這個(gè)功能主要是為后續(xù)的重新開始游戲等功能的準(zhǔn)備。

思考

對(duì)于一個(gè)前端只會(huì)寫js的人,其實(shí)來(lái)搞前端樣式還是有困難的。但是,我們可以“借鑒”呀。
至此之前,后端只要考慮有沒有這個(gè)玩家,現(xiàn)在我們要考慮這個(gè)玩家的狀態(tài)。很明顯,我們需要一個(gè)context的上下文對(duì)象來(lái)保存這個(gè)狀態(tài)。在這個(gè)過(guò)程中,開發(fā)得其實(shí)很蹩腳。有這么幾種關(guān)系,棋盤、規(guī)則、房間、玩家等,這部分需要去做合理地抽象,我希望未來(lái)這個(gè)后臺(tái)是可以通配各種棋牌游戲的,如果我們今天想玩麻將了,我們只要寫前端代碼,還有寫麻將的規(guī)則即可。

實(shí)現(xiàn)

先放一張效果圖

Paste_Image.png

是不是感覺比之前的好看多了,感覺就很高大上,如果是大學(xué)的畢業(yè)設(shè)計(jì),一下子從C變成了A+,老師們都喜歡好看的...

我們來(lái)看下css的代碼(后端猴子最討厭了)

body {
    font-size: 12px;
    line-height: 150%;
    text-align: center;
    background: url(../images/bg.jpg) repeat scroll 0% 0% transparent;
    margin: 0;
    position: relative;
}
.game-box {
    width: 640px;
    margin: 0 auto;
    position: relative;
}
.btn-box {
    padding-left:45px;
}
.btn-box a {
    background: url(../images/btn-bg1.png) center 0 no-repeat;
    height: 75px;
    width: 205px;
    cursor: pointer;
    margin:0 30px;
    display:block;
    font: normal 22px/70px "微軟雅黑";
    float:left;
    color: #480e00;
    text-decoration: none;
}

body是背景,game-box是畫布,btn-box是下面的按鈕。這里面的幾個(gè)參數(shù)還是比較熟悉的,如果有哪些字段不知道什么意思,可以在w3c 上面查一查。這里面比較“神奇”的就是game-box里面的margin了,通過(guò)auto自適應(yīng),可以居中。但是隨即我們就發(fā)現(xiàn)了一個(gè)問(wèn)題,當(dāng)我們發(fā)生monseDown的時(shí)候,獲取的坐標(biāo)是頁(yè)面里面的坐標(biāo),我們?nèi)绾无D(zhuǎn)化為畫布的坐標(biāo)呢?
很明顯我們需要獲取

Paste_Image.png

這么一個(gè)位置,這個(gè)東西糾結(jié)了好久,一直不知道怎么搞,一直找不到現(xiàn)成的方法(前端弱雞)。后來(lái)閱讀別人的代碼中獲取到這么一種思路,逐層往外遞增。

    function getDomXY(a) {
        for (var b = a.offsetLeft,
                     c = a.offsetTop,
                     d = a.offsetParent; null !== d;) b += d.offsetLeft,
                c += d.offsetTop,
                d = d.offsetParent;
        return {
            x: b,
            y: c
        }
    }

在前端中,offsetParent顧名思義,就是獲取這個(gè)對(duì)象的父對(duì)象。
好了,添加了這些,我們其實(shí)已經(jīng)把前端變得“高大上”了。這一部分都是純粹的前端改動(dòng),后臺(tái)并不需要進(jìn)行任何處理。
接下來(lái)我們來(lái)考慮增加準(zhǔn)備這么一個(gè)功能。
前端非常簡(jiǎn)單,我們只要添加一個(gè)按鈕,還有對(duì)應(yīng)的js代碼

    <div class = "btn-box"><a onclick="sendReadyMsg()">準(zhǔn)備好了</a></div>

    function sendReadyMsg(){
        if (isReady == false){
            webSocket.send("ready");
        }
        isReady = true;
    }

但是對(duì)于后端,我們發(fā)現(xiàn)我們?cè)瓉?lái)的簡(jiǎn)單后端模型支持不了。于是我們需要進(jìn)行改造,首先,我們需要一個(gè)上下文對(duì)象來(lái)存用戶的狀態(tài)?,F(xiàn)在我們只用來(lái)保存用戶的準(zhǔn)備狀態(tài)。

  public class UserContext {
        private Session session;

        public UserContext(Session session){
            this.session = session;
        }

        /**
         * 游戲狀態(tài)
         */
        private @Getter @Setter int gameStatus;
        public interface GAME_STATUS {int PENDING  = 0; int READY = 1; int RUNNING = 2;}

        /**
         * 是否準(zhǔn)備完成
         */
        public boolean isReady(){
            return gameStatus == GAME_STATUS.READY;
        }
    }

然后以前room中存用戶的set<Session>變成map<Session, UserContext>.我們來(lái)整理一下整個(gè)準(zhǔn)備動(dòng)作的流程。

Paste_Image.png

簡(jiǎn)書的markdown不支持流程圖真是太不方便了....
按照這個(gè)流程圖,我們只要修改對(duì)應(yīng)的方法即可。非常簡(jiǎn)單,就不貼代碼出來(lái)了。

總結(jié)

再一次回到剛才我們提到的問(wèn)題,就是用戶、規(guī)則、房間等類之間的關(guān)系。這一部分是需要后面好好好好考慮的。雖然現(xiàn)在我也做好了一些抽象,但是可能之前沒做過(guò)相關(guān)的東西,我想還是先繼續(xù)添加一些功能,然后看看之前的模型是否適用。
源代碼下載地址
以往沒有任何做游戲的經(jīng)驗(yàn),如果大家有什么批評(píng)指正,歡迎大家評(píng)論指教。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容