使用Hilo做一个H5接金币类小游戏

Hilo是一个跨终端的互动游戏解决方案。

官网:http://hiloteam.github.io/index.html

 

马上就要端午节了,公司要做一个接粽子的小游戏。网上找了一圈后决定用阿里团队的Hilo库进行开发。

 

游戏页面

游戏页面

游戏代码目录

 

1.安装hilo

npm install hilojs --save

 2.index.vue

<template>
    <div class="hilo" ref="hilo">
        <div class="gameInfo">
            <div class="score">{{score}}</div>
            <div class="time">{{gameTime}}s</div>
        </div>
        <van-popup v-model="scorePopup" style="background: none;overflow: initial;">
            <div class="scorePopup">
                <div class="scorePopup-title">您本次游戏</div>
                <div class="scorePopup-score">
                    {{score}}分
                </div>
            </div>
        </van-popup>
    </div>
</template>

<script>
    import Hilo from "hilojs";
    import Game from "./js/game";
    export default {
        name: '',
        data() {
            return {
                game: new Game(),
                scorePopup: false
            };
        },
        watch: {
            gameTime(val) {
                if (val == 0) { //游戏结束
                    setTimeout(() => {
                        this.scorePopup = true;
                    }, 1500);
                }
            }
        },
        computed: {
            score() {
                return this.game.score
            },
            gameTime() {
                return this.game.gameTime
            }
        },
        methods: {
            
        },
        mounted() {
            this.game.page = this.$refs.hilo;
            this.game.init();
        },

    }
</script>

 

3.游戏图片资源预加载  Asset.js

游戏界面创建前可先加载游戏内需要的图片资源

使用Hilo的LoadQueue的队列下载工具。

export default Hilo.Class.create({
    Mixes: Hilo.EventMixin,
    queue: null,  // 下载类
    bg: null,   // 背景
    bigzZongzi: null,   // 大粽子
    zongzi: null,   // 小粽子
    fruit: null,   // 香蕉
    hand: null,   // 手
    beginBtn: null,   // 开始按钮
    score0: null,   // -1分
    score1: null,   // +1分
    score2: null,   // +2分
    load() {
        let imgs = [{
            id: 'bg',
            src: './images/bg.png'
        },
        {
            id: 'bigzZongzi',
            src: './images/bigzZongzi.png'
        },
        {
            id: 'zongzi',
            src: './images/zongzi.png'
        },
        {
            id: 'fruit',
            src: './images/fruit.png'
        },
        {
            id: 'hand',
            src: './images/hand.png'
        },
        {
            id: 'beginBtn',
            src: './images/beginBtn.png'
        },
        {
            id: 'score0',
            src: './images/score0.png'
        },
        {
            id: 'score1',
            src: './images/score1.png'
        },
        {
            id: 'score2',
            src: './images/score2.png'
        }
        ];
        this.queue = new Hilo.LoadQueue();
        this.queue.add(imgs);
        this.queue.on('complete', this.onComplete.bind(this));
        this.queue.start();
    },
    onComplete() { //加载完成
        this.bg = this.queue.get('bg').content;
        this.bigzZongzi = this.queue.get('bigzZongzi').content;
        this.zongzi = this.queue.get('zongzi').content;
        this.fruit = this.queue.get('fruit').content;
        this.hand = this.queue.get('hand').content;
        this.beginBtn = this.queue.get('beginBtn').content;
        this.score0 = this.queue.get('score0').content;
        this.score1 = this.queue.get('score1').content;
        this.score2 = this.queue.get('score2').content;

        //删除下载队列的complete事件监听
        this.queue.off('complete');
        // complete暴露
        this.fire('complete');
    }
})

4.游戏舞台对象  game.js

import Asset from './Asset'
import Zongzi from './Zongzi'
import Hand from './hand'
export default class game {
    constructor(page) {
        this.page = page
        //设置的游戏时间
        this.setGameTime = 30
        this.gameTime = 0
        this.gameStatus = "ready"
        /*
          play 游戏开始
          ready 游戏结束
        **/
        // 下载队列
        this.asset = new Asset()

        // 画布对象
        this.stage = null

        // 画布信息 
        this.width = innerWidth * 2
        this.height = innerHeight * 2 < 1334 ? innerHeight * 2 : 1334
        this.scale = 0.5

        // 定时器对象
        this.ticker = null

        //粽子对象
        this.Zongzi = null
        //粽子下落速度
        this.enemySpeed = 700
        //粽子生成速度
        this.createSpeed = 400
        //接粽子的手
        this.hand = null
        //开始按钮
        this.beginBtn = null
        //分数
        this.score = 0


    }
    init() {
        this.asset.on('complete', function () {
            this.asset.off('complete')
            this.initStage()
        }.bind(this));
        this.asset.load()
    }
    initStage() {
        // 舞台
        this.stage = new Hilo.Stage({
            renderType:'canvas',
            width: this.width,
            height: this.height,
            scaleX: this.scale,
            scaleY: this.scale,
            container: this.page
        });
        this.stage.enableDOMEvent([Hilo.event.POINTER_START, Hilo.event.POINTER_MOVE, Hilo.event.POINTER_END]);

        // 启动定时器刷新页面 参数为帧率
        this.ticker = new Hilo.Ticker(60)
        // 舞台添加到定时队列中
        this.ticker.addTick(this.stage)
        // 添加动画类到定时队列
        this.ticker.addTick(Hilo.Tween);
        //启动ticker
        this.ticker.start(true);

        this.initBg();

        this.initBeginBtn();

        //this.initZongzi();

        //this.initHand();

    }
    initBg() {  //初始化背景
        let bgImg = this.asset.bg;
        new Hilo.Bitmap({
            id: 'bg',
            image: bgImg,
            scaleX: this.width / bgImg.width,
            scaleY: this.height / bgImg.height
        }).addTo(this.stage);
    }
    initBeginBtn() { //初始化开始按钮
        this.beginBtn = new Hilo.Bitmap({
            id: 'beginBtn',
            image: this.asset.beginBtn,
            //width: this.asset.beginBtn.width,
            //height: this.asset.beginBtn.height,
            x: (this.width - this.asset.beginBtn.width) / 2,
            y: this.height - this.asset.beginBtn.height - 200,
            rect: [0, 0, this.asset.beginBtn.width, this.asset.beginBtn.height]
        }).addTo(this.stage, 1);
        this.beginBtn.on(Hilo.event.POINTER_START, this.startGame.bind(this))

    }
    startGame() {   //开始游戏
        this.initZongzi();
        this.initHand()
        //this.beginBtn.removeFromParent()
        this.stage.removeChild(this.beginBtn)
        this.gameTime = this.setGameTime;
        this.score = 0;
        this.gameStatus = "play"
        this.calcTime()
    }
    calcTime() { //游戏时间
        setTimeout(() => {
            if (this.gameTime > 0) {
                this.gameTime--;
                this.calcTime()
            } else {
                this.gameOver()
            }
        }, 1000);
    }
    gameOver() {//游戏结束
        this.Zongzi.stopCreateEnemy()
        this.gameStatus = "ready"
        this.initBeginBtn()
        //this.hand.removeChild(this.hand.score)
        this.stage.removeChild(this.hand)
    }
    initZongzi() {//初始化粽子
        this.Zongzi = new Zongzi({
            id: 'Zongzi',
            height: this.height,
            width: this.width,
            enemySpeed: this.enemySpeed,
            createSpeed: this.createSpeed,
            pointerEnabled: false, // 不关闭事件绑定 无法操作舞台
            zongziList: [this.asset.bigzZongzi, this.asset.zongzi, this.asset.fruit]
        }).addTo(this.stage, 2)
        //舞台更新
        this.stage.onUpdate = this.onUpdate.bind(this);
    }
    initHand() {//初始化手
        this.hand = new Hand({
            id: 'hand',
            img: this.asset.hand,
            height: this.asset.hand.height,
            width: this.asset.hand.width,
            x: this.width / 2 - this.asset.hand.width / 2,
            y: this.height - this.asset.hand.height + 30
        }).addTo(this.stage, 1);
        Hilo.util.copy(this.hand, Hilo.drag);
        this.hand.startDrag([-this.asset.hand.width / 4, this.height - this.asset.hand.height + 30, this.width - this.asset.hand.width / 2, 0]);
    }
    onUpdate() {//舞台更新
        if (this.gameStatus == 'ready') {
            return
        }
        this.Zongzi.children.forEach(item => {
            if (this.hand.checkCollision(item)) {
                // 碰撞了
                item.over();
                this.score += item.score;
                switch (item.score) {
                    case -1:
                        this.hand.addScore(this.asset.score0)
                        break;
                    case 1:
                        this.hand.addScore(this.asset.score1)
                        break;
                    case 2:
                        this.hand.addScore(this.asset.score2)
                        break;

                    default:
                        break;
                }
            }
        })
    }
}

5.粽子对象

Zongzi.js

import SmallZongzi from './SmallZongzi'
let Enemy = Hilo.Class.create({
    Extends: Hilo.Container,
    SmallZongziImg: null,
    timer: null, // 定时器
    zongziList: [],
    enemySpeed: 0,
    createSpeed: 0,
    score: [2, 1, -1],
    tween: null,

    constructor: function (properties) {
        Enemy.superclass.constructor.call(this, properties);

        //this.onUpdate = this.onUpdate.bind(this);
        //this.createSmallZongzi()
        this.tween = Hilo.Tween;
        this.creatEnemy();
        this.beginCreateEnemy();
    },
    random(lower, upper) {
        return Math.floor(Math.random() * (upper - lower + 1)) + lower;
    },
    creatEnemy() { // 生成粽子
        let number = this.random(0, 100);
        let index = null;
        if (number < 27) {  //生成不同种类粽子概率
            index = 0
        } else if (number < 55) {
            index = 1
        } else {
            index = 2
        }
        let hold = new SmallZongzi({
            image: this.zongziList[index],
            rect: [0, 0, this.zongziList[index].width, this.zongziList[index].height]
        }).addTo(this);

        hold.x = this.random(100, (this.width - 100));

        hold.y = -300 * Math.random();

        hold.score = this.score[index]

        this.tween.to(hold, {
            y: this.height + 200
        }, {
            duration: 1400 / this.enemySpeed * 1000,
            loop: false,
            onComplete: () => {
                hold.removeFromParent()
            }
        });

    },
    beginCreateEnemy() {//开始生成
        this.timer = setInterval(() => {
            this.creatEnemy();

        }, this.createSpeed);
    },
    stopCreateEnemy() {//停止生成并全部移除
        clearInterval(this.timer)
        this.removeAllChildren()
    },
    checkCollision(enemy) {//碰撞检测
        for (var i = 0, len = this.children.length; i < len; i++) {
            if (enemy.hitTestObject(this.children[i], true)) {
                return true;
            }
        }
        return false;
    }
})

export default Enemy

SmallZongzi.js

let SmallZongzi = Hilo.Class.create({
  Extends: Hilo.Bitmap,
  constructor: function (properties) {
    SmallZongzi.superclass.constructor.call(this, properties);
    this.onUpdate = this.onUpdate.bind(this);
  },
  over(){
    this.removeFromParent();
  },
  onUpdate() {
    if (this.parent.height < this.y) {
      this.removeFromParent();
      return
    }
  }
})

export default SmallZongzi

6.手对象   hand.js

let hand = Hilo.Class.create({
    Extends: Hilo.Container,

    // 图
    img: null,
    //碗
    bowl: null,
    //分数
    score: null,

    constructor(properties) {
        hand.superclass.constructor.call(this, properties)
        this.initHand()
        this.initBowl()
    },
    initHand() {  //初始化背景
        new Hilo.Bitmap({
            id: 'hand',
            image: this.img,
            rect: [0, 0, this.img.width, this.img.height]
        }).addTo(this);
    },
    initBowl() { //初始化碗
        this.bowl = new Hilo.Bitmap({
            id: 'bowl',
            //background: 'rgba(255,255,255,0.4)',
            rect: [0, 0, this.img.width / 3, 10],
            x: this.img.width / 3,
            y: 50
        }).addTo(this);
    },
    addScore(image) { //加分
        this.score = new Hilo.Bitmap({
            id: 'score',
            image: image,
            rect: [0, 0, image.width, image.height],
            x: (this.img.width - image.width) / 2,
            y: -image.height
        }).addTo(this);

        Hilo.Tween.to(this.score, {
            x: (this.img.width - image.width / 2) / 2,
            y: -2 * image.height,
            alpha: 0,
            width: image.width / 2,
            height: image.height / 2
        }, {
            duration: 600,
            //delay: 100,
            ease: Hilo.Ease.Quad.EaseIn,
            onComplete: () => {
                
            }
        });
    },

    // 碰撞检测
    checkCollision(enemy) {
        if (enemy.hitTestObject(this.bowl, true)) {
            return true;
        }
        return false;
    }
})

export default hand

 

一个简单的守护进程可以通过以下步骤实现: 1. 使用 `fork()` 函数创建子进程,然后让父进程退出,使子进程成为孤儿进程,从而与终端断开关联。 2. 使用 `setsid()` 函数创建新的会话,使子进程成为新的会话组长和进程组长,也就是守护进程。 3. 使用 `chdir()` 函数将当前工作目录切换到根目录 `/`,以避免影响到其他目录和文件。 4. 使用 `umask()` 函数设置文件创建时的权限掩码,以避免出现安全问题。 5. 使用 `close()` 函数关闭标准输入、标准输出和标准错误流,以避免输出到终端或其他地方。 6. 在一个无限循环中,使用 `sleep()` 函数等待 60 秒,然后输出字符串 `hilo`。 具体实现方法如下: ```c #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/stat.h> #include <sys/types.h> int main() { pid_t pid; pid = fork(); if (pid == -1) { perror("fork"); exit(1); } else if (pid > 0) { // 父进程退出 exit(0); } // 子进程 setsid(); // 创建新会话 chdir("/"); // 切换工作目录 umask(0); // 设置文件创建时的权限掩码 close(STDIN_FILENO); // 关闭标准输入 close(STDOUT_FILENO); // 关闭标准输出 close(STDERR_FILENO); // 关闭标准错误 while (1) { sleep(60); // 等待 60 秒 printf("hilo\n"); // 输出 hilo fflush(stdout); // 刷新输出缓冲区 } return 0; } ``` 首先,使用 `fork()` 函数创建子进程。如果 `fork()` 函数返回值为 `-1`,则说明创建子进程失败,此时使用 `perror()` 函数输出错误信息,并退出程序。如果 `fork()` 函数返回值大于 `0`,则说明当前进程是父进程,此时退出程序。如果 `fork()` 函数返回值为 `0`,则说明当前进程是子进程,此时调用 `setsid()` 函数创建新的会话,并将当前进程设置为新的会话组长和进程组长。然后,使用 `chdir()` 函数将当前工作目录切换到根目录 `/`,使用 `umask()` 函数设置文件创建时的权限掩码为 0。着,使用 `close()` 函数关闭标准输入、标准输出和标准错误流。最后,在一个无限循环中,使用 `sleep()` 函数等待 60 秒,然后输出字符串 `hilo`,并使用 `fflush()` 函数刷新输出缓冲区,以确保输出立即被打印到文件或终端。
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值