9.2 打飞机游戏示例

游戏简介

一款飞行射击类游戏。Cocos Shooting 操作简单,节奏明快,是纵轴射击的经典之作。开始游戏前需要支付Cocos,游过程中操纵自己的飞机来击落敌机,获得Cocos和弹药补给,以此来强化飞机。被击毁后可消耗Cocos复活或重新挑战。可以升级装备,让自己的战机更强大,战胜每一个BOSS。

游戏地址(需安装Cocospay插件)

游戏项目源码

游戏开发示例

合约开发

合约部署的方法详见:5.7 合约开发和部署的多种方式

此游戏合约代码如下:
注意:

  1. 接口init, 用于合约初始化,一般用合约的创建者负责执行。所以第一行有执行权限控制。特别强调:需要手动调用执行,需要手动调用执行,需要手动调用执行!!!!
  2. public_data 用于存储合约上下文环境的数据。怎么理解呢? 你把合约看成一个独立的对象的话,这一块区域就是这个对象的状态。但这个状态比较奇葩,在读取和写入的之后,都需要手动读链和写链。
-- 奖池初始化
function init()
  -- 资产精度
  if ( public_data.accuracy  == nil ) then
      public_data.accuracy  = 100000
  end 

  -- 设置奖品列表
  if ( public_data.bomb == nil ) then
    public_data.bomb = { }
  end

  if ( public_data.weapon == nil ) then
    public_data.weapon = { }
  end

  if ( public_data.employee == nil ) then
     public_data.employee = { }
  end

  -- 设置概率
  if ( public_data.draw_radio == nil ) then
    public_data.draw_radio = { 5, 20, 20, 5, 5, 7, 20, 2, 15, 1}
    public_data.draw_name = { 'no','money','bomb', 'money', 'bomb','money','weapon','money', 'employee', 'money' }
    public_data.reward = { 0, 80, 1, 120, 2, 200, 1, 300, 1, 400}
  end
  write_list={public_data={accuracy=true, draw_radio=true, draw_name=true, reward=true}}
  chainhelper:write_chain()
  chainhelper:log('##result##:{"status": 1, "msg": "init finished!"}');
end

function put_reward (reward_type, item_ids)
  assert(chainhelper:is_owner(),'You`re not the contract`s owner')
  local arr_item_ids = cjson.decode(item_ids)
  read_list={public_data={bomb=true, weapon=true, employee=true}}
  chainhelper:read_chain()
  if ( public_data.bomb == nil ) then
    public_data.bomb = { }
  end

  if ( public_data.weapon == nil ) then
    public_data.weapon = { }
  end

  if ( public_data.employee == nil ) then
    public_data.employee = { }
  end

  if reward_type == 1 then
    public_data.bomb = { }
    for key,value in pairs(arr_item_ids) do
      local is_find = false
      for k, v in pairs(public_data.bomb) do
        if v == value then
         is_find = true
        end
      end

      if is_find == false then  
        table.insert(public_data.bomb, value);
      end
    end
  elseif reward_type == 2 then
    public_data.weapon = { }
    for key,value in pairs(arr_item_ids) do
      local is_find = false
      for k, v in pairs(public_data.weapon) do
        if v == value then
         is_find = true
        end
      end

      if is_find == false then  
        table.insert(public_data.weapon, value);
      end
    end
  elseif reward_type == 3 then
    public_data.employee = { }
    for key,value in pairs(arr_item_ids) do
      local is_find = false
      for k, v in pairs(public_data.employee) do
        if v == value then
         is_find = true
        end
      end

      if is_find == false then
        table.insert(public_data.employee, value);
      end
    end
  end
  write_list={public_data={bomb=true, weapon=true, employee=true}}
  chainhelper:write_chain()
  chainhelper:log('##result##:{"status": 1, "msg": "put_reward finished!", "bomb": ""}');
end

-- 抽奖
function draw( user_name, amount )
  -- 扣除投注额
  read_list={public_data={accuracy=true, draw_radio=true, draw_name=true, reward=true}}
  chainhelper:read_chain()
  
  chainhelper:transfer_from_caller(contract_base_info.owner,  amount * public_data.accuracy, 'COCOS', true)
 
  result = {} -- 抽奖结果
 
  -- 总权重
  local start_prop = 0
  local rand_value = chainhelper:random() % 100
  local current = 1
 
  -- 随机数匹配权重
  for key,value in pairs(public_data.draw_radio) do
    if ( rand_value < start_prop + value) then
      result['draw'] = public_data.draw_name[key]
      result['amount'] = public_data.reward[key]
      result['pos'] = key
      break
    else
      start_prop = start_prop + value
    end
  end
  
  local reward_id = nil
  -- 发放奖金
  if ( result['draw'] == 'money' ) then
    --发放代币
    chainhelper:transfer_from_owner( user_name, result['amount'] * public_data.accuracy, 'COCOS', true)
  elseif (result['draw'] == 'bomb') then
    --发放炸弹
    read_list={public_data={ bomb= true}}
    chainhelper:read_chain()
    local current_bomb = 0;
    while (current_bomb < result['amount']) do
      current_bomb = current_bomb + 1
      reward_id = table.remove(public_data.bomb)
    end
    write_list=read_list
  elseif (result['draw'] == 'weapon') then
    --发放武器
    read_list={public_data={ weapon= true}}
    chainhelper:read_chain()
    reward_id = table.remove(public_data.weapon)
    write_list=read_list
    
  elseif (result['draw'] == 'employee') then
    --发放员工
    read_list={public_data={ employee= true}}
    chainhelper:read_chain()
    reward_id = table.remove(public_data.employee)
    write_list=read_list
  end

  if(result['draw'] ~= 'money') then
    if (reward_id) then
      chainhelper:transfer_nht_from_owner( user_name, reward_id, true)
    else
      --奖池空时的容错 --统一当没抽到奖励处理
      result['draw'] = 'no'
      result['amount'] = 0
      result['pos'] = 0
    end
  end
  
  if(reward_id ~= nil) then
    chainhelper:write_chain()
  end

  chainhelper:log('##result##:{"status": 1, "msg": "draw finished!", "draw": "'..result['draw']..'","amount":"'..result['amount']..'","pos":"'..result['pos']..'"}');
end

function getTableObjects()
  read_list={public_data={bomb=true, weapon=true, employee=true}}
  chainhelper:read_chain()

  local bomb = cjson.encode(public_data.bomb)
  chainhelper:log('#getTableObjects==bomb=#'..bomb)
end

客户端开发

打飞机游戏不同于骰子游戏,它分服务端和客户端。
游戏的客户端连接Cocos-BCX,通过Cocos-BCX链上的合约来实现玩家与游戏之间的COCOS 的交易。

  1. 首先需引入JSSdk 文件以及链接、签名工具包:
// import BCX from 'bcx.min.js' 
require('./core.min');
require('./plugins.min');
  1. 获取sdk对象
    a. 建立链接并初始化与链交互的sdk接口对象
var _configParams = {
    ws_node_list:[
        {url:"ws://test.cocosbcx.net",name:"Cocos - China - Beijing"},   
     ],
     networks:[
        {
            core_asset:"COCOS",
            chain_id:"c1ac4bb7bd7d94874a1cb98b39a8a582421d03d022dfa4be8c70567076e03ad0" 
        }
     ], 
    faucet_url:"http://test-faucet.cocosbcx.net",
    auto_reconnect:true,
    real_sub:true,
    check_cached_nodes_data:false
 }
b. 检测移动端钱包[AndroidWallet](https://github.com/Cocos-BCX/AndroidWallet)、[iOSWallet](https://github.com/Cocos-BCX/IOSWallet)或[Google插件钱包](https://github.com/Cocos-BCX/CocosPay)注入的sdk对象是否存在,如果存在则覆盖 1 中创建的sdk接口对象。(移动端钱包和Google插件钱包会通过注入方式,在window上挂载一个BcxWeb对象.

下面则是接入Cocos-BCX链的核心方法,当然还有些其他方法,比如:获取钱包模式下的账号,读取当前用户账户下所有可在对应游戏中使用的道具,删除道具等在这里就不一一列举了,可在github上下载源码自行学习。

initSDK (callback) {
        this.isLoginBcl = false;
        this.account = null;
        this.userId = null;
        this.privateKey = null;
        this.contractName = "contract.ccshooter.lottery";//合约名称
        this.upgradeContract = "contract.ccshooter.upgrade";//升级的合约
        
        if (window.BcxWeb) {
            this.bcl =  window.BcxWeb;
            console.log("===bcl---")
            if (callback) {
                callback(null);
            }
        }else{
            
            console.log("===bcl--cocos-")
            let self = this
            self.bcl = new BCX(_configParams);
            Cocosjs.plugins(new CocosBCX())
            //connect pc-plugin between sdk
            Cocosjs.cocos.connect('My-App').then(connected => {
                console.log("connected=="+connected)
                if (!connected) {
                    //检测一下注入
                    self.checkWindowBcx(function(is_success){
                        console.log("is_success==",is_success)
                        if(is_success){
                            if (callback) {
                                console.log("is_success==222")
                                callback(null)
                            }
                        }else{
                            //此时基本可以认定没有cocospay 给用户提示
                            cc.gameSpace.showTips(cc.gameSpace.text.no_cocos_pay);
                        }
                    })
                    return false
                }

                //此时走的是coocspay客户端
                const cocos = Cocosjs.cocos
                self.bcl = cocos.cocosBcx(self.bcl);

                if (callback) {
                    callback(null);
                }
            }).catch(function(e){
                console.log("connect error---"+JSON.stringify(e))
            })

        }
    },

服务端开发

服务端接入Cocos-BCX,调用方式稍有不一样,下面是游戏的服务端连接Cocos-BCX的接口的相关示例:

首先也需要引入文件:

var bclLibs = require('./lib/bcx.node');

初始化sdk:

let bcx = bclLibs.createBCX({
     ws_node_list:[
        {url:"ws://test.cocosbcx.net",name:"Cocos - China - Beijing"},   
     ],
     networks:[
        {
            core_asset:"COCOS",
            chain_id:"c1ac4bb7bd7d94874a1cb98b39a8a582421d03d022dfa4be8c70567076e03ad0" 
        }
     ], 
    faucet_url:"http://test-faucet.cocosbcx.net",
    auto_reconnect:true,
    real_sub:true,
    check_cached_nodes_data:false       
});

登录Cocos-BCX账户:

bcx.passwordLogin({
        account:account,//query.loginUserName,
        password:password
    }).then(res=>{
        console.info("bcx passwordLogin res",res);
        if(call_back){
            call_back()
        }
    });

这里只说了一些基础的方法,只是游戏的一部分,若开发者想学习全部代码,可自行查看游戏项目源码

Updated 7 months ago


9.2 打飞机游戏示例


Suggested Edits are limited on API Reference Pages

You can only suggest edits to Markdown body content, but not to the API spec.