废话(前言)

现在游戏多了,不过总是感觉不太对自己的口味,每个游戏都感觉和自己想象中的要差了那么一点点,所以我决定尝试着自己写一个游戏。

因为从来没做过游戏开发,所以所有游戏机制的实现都只能是在网上查或者自己摸索,如果大家在看文章( 或视频 )的时候有更好的实现方法,请一定要告诉我。

那么策划下这个游戏吧,我的口味是怎样的呢:

  1. 随时可以玩。由于我上班的时候有时候觉得很无聊,也许想放松一下,所以最好这个游戏是网页版的,随时打开随时玩。
  2. 最好是要用到脑子玩。哼,大家辣么聪明,肯定要靠智力虐人的对吧,那么应该是一个能让人越动脑就越厉害的游戏。
  3. 不要氪金。消费内容一定不能影响游戏平衡,或者干脆没有消费内容,装备全靠打。
  4. 有没有伙伴,有多少伙伴,都能玩。希望喜欢单机挑战的小伙伴能玩,情侣能玩,宿舍能玩,很多朋友一起也能玩。

综上所述,我决定做的这个游戏就是!!!——炉石传说的网页版,emmmmmm……,没事,先模仿再提高吧。


然后再说一下这个视频的受众和需要的基础,因为这个视频没有使用高深的技术,所以想学习到很底层技术的同学可能会失望,这是游戏线上beta版本的地址,大家可以去试玩一下,如果觉得感兴趣,自己也想开发一款这样的游戏,那么你可以继续看了。

我会将代码按批次开源,这个项目在视频出完之前,暂时不接受贡献,因为会打乱我视频的节奏,希望大家理解,等项目出完之后,会接受pull request,所以现阶段对项目想改善的可以直接向我提意见。

由于是网页版本的游戏,那么需要一定的前端基础,当然没有基础的你也可以图个乐子。既然是个网络游戏,那么肯定是有后端的,所以需要掌握一点后端思想。最次,你也要知道编程是个什么东西,然后才能享受看别人敲代码的乐趣。

下面就是正文内容,我们就先进行技术选型,把框架搭起来,数据交互能够联通。


第一回合(准备开始)

先安装需要的库,不使用多厉害的游戏引擎了,就使用最方便开发的技术来实现。那我就选择了vue,如果有同学想用react或者angular或者jquery,都可以的。那我们先安装vue,vue-router,先把游戏的页面搭建出来。

这里我就使用vue-cli,这个呢是vue官方出的一个脚手架,就是帮你初始化一个项目的。那我们先在命令行里执行:

npm install -g @vue/cli

先在全局安装好vue-cli,然后执行vue-cli的命令:

vue create card-game-client

选择Manually select features,会有一些选项要求选择,我们只需要:vue-router,vuex,babel

vue-router为了以后发布方便不使用history模式。

然后再要初始化一个后台项目,创建文件夹card-game-server,为了方便,我就直接用nodejs作为游戏后台了,先初始化一个express项目,在目录下执行:

npm init

初始化npm,然后再安装需要的库:

npm i express body-parser cors log4js --save

不过作为一个游戏来说,肯定数据交互是不能用http请求的,那就使用websocket技术来和后台进行数据交互,我就使用socketio这个库了,继续在命令行执行:

npm i socket.io --save

好。那么就开始激动人心的第一步,hello world。


首先大家在client项目的src文件夹下把原来的views删除,创建一个叫pages的文件夹,存放我们的页面,这一步很重要,它主要目的是——我比较喜欢pages这个单词。创建以后游戏主要场景页面,GameTable.vue:

<template>
    <div></div>
</template>

<script>
export default {
    name: "GameTable"
}
</script>

在GameTable加载的完成后,自动连接服务器,并发送一个hello的消息:

<template>
    <div>{{message}}</div>
</template>

<script>
import * as io from 'socket.io-client';

export default {
    name: "GameTable",
    data() {
        return {
            message: ""
        }
    },
    mounted() {
        this.socket = io.connect('http://localhost:4000');
        this.socket.emit('hello');
    }
}
</script>

页面写好之后,不要忘记修改router,打开router.js,删除之前默认配置,把我们的新页面加进去:

import Vue from 'vue'
import Router from 'vue-router'
import GameTable from './pages/GameTable.vue'

Vue.use(Router)

export default new Router({
  routes: [
    {
      path: '/',
      name: 'gameTable',
      component: GameTable
    }
  ]
})

App.vue中也有一些默认生成的dom和css,删除掉不需要的:

<template>
  <div id="app">
    <router-view/>
  </div>
</template>

<style>
#app {
  font-family: 'Avenir', Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>

客户端发送写好了,来写一下服务端处理程序,首先在server的文件夹下创建app.js文件,在app.js文件中初始化服务器:

let http = require('http');
let express = require('express');
let cors = require('cors');
let bodyParser = require('body-parser');
let socket = require("socket.io");
let app = express();

app.use(cors());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: false}));

let server = http.createServer(app);
let socketServer = socket(server);

server.listen(4001, function () {
    console.log("listen");
});
socketServer.on('connection', function (socket) {
    console.log("connect one on :" + new Date().toLocaleString());
    socket.on('hello', function () { // 监听hello事件
        socket.emit('world', {
            message: 'hello world'
        })
    });

    socket.on('disconnect', function () {
        console.log("disconnect one on :" + new Date().toLocaleString());
    });

});

let socketServer = socket(server);这行代码创建了一个socket服务,然后通过监听事件和发送消息来和客户端互动。

接下来就在server目录运行node app.js,在client目录运行npm run serve,就能运行前端和后端,如果在页面上看到hello world,就证明框架搭建完成了。


接下来,继续下一步,对战界面的绘制。

根据市面上的卡牌游戏设计,对战最基本是有两个角色栏(对战双方),两个手牌区(对战双方),一张对战桌。所以,我们的对战区域就长这样:

先把桌面和己方手牌区域画出来,在GameTable.vue中,添加下面的代码:

<div class="app">
    <div class="table">
        <div class="other-card-area">

        </div>
        <div class="my-card-area">

        </div>
    </div>

    <div class="my-card">

    </div>
</div>

为了让界面更加容易区分,我们给各个区域加上鲜明的颜色:

.app {
    width: 100%;
    height: 100%;
    overflow: hidden;
    user-select: none;
}

.my-card {
    position: absolute;
    bottom: 20px;
    width: 100%;
    min-height: 170px;
    display: flex;
    justify-content: center;
    background: #f00;
}

.table {
    width: 100%;
    height: 100%;
}

.my-card-area {
    width: 100%;
    height: 33%;
    min-height: 170px;
    position: absolute;
    bottom: 210px;
    display: flex;
    padding: 10px;
    box-sizing: border-box;
    justify-content: center;
    background-color: #0f0;
}

.other-card-area {
    width: 100%;
    min-height: 170px;
    padding: 10px;
    display: flex;
    justify-content: center;
    box-sizing: border-box;
    flex-wrap: wrap;
    background-color: #00f;
}

那么看到的效果应该是这样的:

做到这一步,相信大家也能看出这个游戏的雏形了吧……emmmmmm,下一章进度加快吧。

再发一次游戏最新进度的线上beta版地址,大家看了有兴趣的,就等更新吧~


2 条评论

vbyzc · 2019年1月7日 09:37

想从头教到尾吗,那得几十章?

    xiejingyang · 2019年1月7日 10:46

    哈哈哈,怕是要哦,我自己研究就研究了大半年,尽量精简点语言

发表评论

电子邮件地址不会被公开。 必填项已用*标注