香雨站

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 77|回复: 1

微信小游戏制作指南(五)——开始游戏

[复制链接]

5

主题

6

帖子

16

积分

新手上路

Rank: 1

积分
16
发表于 2023-1-12 07:35:52 | 显示全部楼层 |阅读模式
本节对游戏游玩界面进行开发,主要涉及宝石生成、宝石选中、宝石移动、宝石消除、得分计算 、得分展示、游玩音效等内容。
一、游玩前的数据初始化(MyData.js)
  gamePlayingInit() {
    this.beginTime = new Date().getTime(); //游戏开始时间
    this.deltaTime = 0; //游戏跳过时间(用于载入)
    this.pauseTime = 0; //游戏暂停时间(用于保存等时机暂停游戏)
    this.gameOver = 0; //游戏结束:1无路可走 2游戏时间到 3主动放弃
    this.scorePower = 1; //多次连续消除会使得分一直翻倍
    this.scoreModel = 1; //当得分模式为-1时会变成扣分
    this.scoreAdd = 0; //需要增加的得分
    this.playingSets = new Array();
    if (this.gameModel == 1) {
      for (let i=0;i<this.model1PlaySets.length;i++) {
        this.playingSets = PLAY_SET_SELECTS[this.model1PlaySets];
      }
    }
    this.gemColors = DEFAULT_GEM_COLORS.slice(); //宝石颜色列表
    this.gemIcons = DEFAULT_GEM_ICONS.slice(); //宝石图案列表
    this.curSelectedIndex = -1; //当前选中的宝石
    this.pathIndexs = new Array(); //宝石移动的路径列表
    this.clearIndexs = new Array(); //需要消除的宝石列表
    this.magicGemPercent = this.playingSets[3]/(this.playingSets[1]+this.playingSets[3])*this.playingSets[11]; //魔法宝石生成百分比
    this.newGemColors = new Array(); //新宝石颜色列表
    this.newGemIcons = new Array(); //新宝石图案列表
    this.generateNewGems(5); //随机生成5个宝石
    this.randomIndexs = DEFAULT_ALL_INDEXS.slice(); //宝石生成的随机位置列表
    this.newGemIndexs = new Array(); //随机生成位置列表
    this.putGenerateGems(5); //将生成的宝石置于方格位置内
    this.generateNewGems(); //随机生成新的宝石(提示栏的预告宝石)
    this.propIcons = new Array();
    this.generateNewProps(); //随机生成新的道具(提示栏的可用道具)
  }
  generateNewGems(number) {
    if (number == null) number = this.playingSets[10];
    for (let i=0;i<number;i++) {
      let random1 = Math.random();let random2 = Math.random();
      let randomColor = random1 < this.magicGemPercent?9+parseInt(this.playingSets[3]*random2):parseInt(this.playingSets[1]*random2);
      this.newGemColors = DEFAULT_ALL_COLORS[randomColor];
      if (this.playingSets[2] == 0) {
        this.newGemIcons = DEFAULT_ALL_ICONS[randomColor];
      } else {
        let random3 = Math.random();
        let randomIcon = parseInt(this.playingSets[2]*random3);
        this.newGemIcons = DEFAULT_ALL_ICONS[randomIcon];
      }
    }
  }
  putGenerateGems(number) {
    if (number == null) number = this.playingSets[10];
    if (this.randomIndexs.length < number) {this.gameOver = 1;return 0;}
    for (let i=0;i<number;i++) {
      let random = parseInt(this.randomIndexs.length*Math.random());
      this.gemColors[this.randomIndexs[random]] = this.newGemColors;
      this.gemIcons[this.randomIndexs[random]] = this.newGemIcons;
      this.randomIndexs.splice(random,1);
    }
  }
  generateNewProps(number) {
    if (number == null) number = this.playingSets[6];
    for (let i=0;i<number;i++) {
      let random = parseInt(number*Math.random());
      this.propIcons = DEFAULT_ALL_PROPS[random];
    }
  }
二、游玩前的渲染初始化(MyRender.js)
(一)渲染时的信息
//渲染时的信息
let background = null;let buttonUpWidth = 48;
let fontSize = 14;let text = "";let texts = new Array();
let splitWidth = 64;let splitHeight = 64;
let renderGemColors = null;
let renderGemIcons = null;
let renderPropIcons = null;
let clearHideShowTimes = 8; //清除时隐显次数
let curClearHideShowTimes = 0; //myData.frame%6
let oldGemPutIndex = -1; //依次放置,间隔myData.frame%7
let scoreAddShowTime = 50; //绘制得分所需帧数
let curAddScoreShowTime = 0;
let curAddScore = 0;
(二)宝石和道具渲染
主要包括宝石颜色渲染、宝石图标渲染、道具图标渲染,该初始化操作在MyRender的构造函数的doMainSets里面进行,当操作者更改了mainSets,这时也会同步更新渲染结果。
  doMainSets(index) {
    if (index == null) {
      this.setBackground();
      myMusic.setBgm(myData.mainSets[1]);
      this.setRenderGemColors();
      this.setRenderGemIcons();
      myMusic.setBgmVolume(myData.MAIN_SET_SELECTS()[6][myData.mainSets[6]]);
      myMusic.setSoundEffectVolume(myData.MAIN_SET_SELECTS()[7][myData.mainSets[7]]);
    } else if (index == 0) {
      this.setBackground();
    } else if (index == 1) {
      myMusic.setBgm(myData.mainSets[1]);
    } else if (index == 2) {
      this.setRenderGemColors();
    } else if (index == 3) {
      this.setRenderGemIcons();
    } else if (index == 4) {
      this.setRenderGemColors();
    } else if (index == 5) {
      this.setRenderGemIcons();
    } else if (index == 6) {
      myMusic.setBgmVolume(myData.MAIN_SET_SELECTS()[myData.mainSets]);
    } else if (index == 7) {
      myMusic.setSoundEffectVolume(myData.MAIN_SET_SELECTS()[myData.mainSets]);
    }
  }
  setBackground() {
    background = myData.mainSets[0]==0?background1:background2;
  }
  setRenderGemColors() {
    renderGemColors = new Array();
    renderGemColors.push(0); //0表示渲染空白图像
    let tempSet = 0;let tempSets;let tempMagicGemSets;
    if (myData.mainSets[2] == 3) {
      tempSet = parseInt(Math.random()*3);
    } else tempSet = myData.mainSets[2];
    if (tempSet == 0) {
      tempSets = [1,2,3,4,5,6,7,8,9];
      tempMagicGemSets = [10,11,12];
    } else if (tempSet == 1) {
      tempSets = [13,14,15,16,17,18,19,20,21];
      tempMagicGemSets = [22,23,24];
    } else {
      tempSets = [25,26,27,28,29,30,31,32,33];
      tempMagicGemSets = [34,35,36];
    }
    if (myData.mainSets[4] == 2) { //随机排序
      for (let i=0;i<9;i++) {
        let tempRandom = parseInt(Math.random()*tempSets.length);
        renderGemColors.push(tempSets[tempRandom]);
        tempSets.splice(tempRandom,1);
      }
      renderGemColors.push(tempMagicGemSets[0]);
      renderGemColors.push(tempMagicGemSets[1]);
      renderGemColors.push(tempMagicGemSets[2]);
    } else if (myData.mainSets[4] == 1) { //倒序
      for (let i=0;i<9;i++) {
        renderGemColors.push(tempSets[8-i]);
      }
      renderGemColors.push(tempMagicGemSets[0]);
      renderGemColors.push(tempMagicGemSets[1]);
      renderGemColors.push(tempMagicGemSets[2]);
    } else { //顺序
      for (let i=0;i<9;i++) {
        renderGemColors.push(tempSets);
      }
      renderGemColors.push(tempMagicGemSets[0]);
      renderGemColors.push(tempMagicGemSets[1]);
      renderGemColors.push(tempMagicGemSets[2]);
    }
  }
  setRenderGemIcons() {
    renderGemIcons = new Array();
    renderGemIcons.push(0); //0表示渲染空白图像
    let tempSet = 0;let tempSets;
    if (myData.mainSets[3] == 3) {
      tempSet = parseInt(Math.random()*3);
    } else tempSet = myData.mainSets[3];
    if (tempSet == 0) {
      tempSets = [1,2,3,4,5,6,7,8,9,10,11,12];
    } else if (tempSet == 1) {
      tempSets = [13,14,15,16,17,18,19,20,21,22,23,24];
    } else if (tempSet == 2) {
      tempSets = [25,26,27,28,29,30,31,32,33,34,35,36];
    } else {
      tempSets = [37,38,39,40,41,42,43,44,45,46,47,48];
    }
    if (myData.mainSets[5] == 2) { //随机排序
      for (let i=0;i<12;i++) {
        let tempRandom = parseInt(Math.random()*tempSets.length);
        renderGemIcons.push(tempSets[tempRandom]);
        tempSets.splice(tempRandom,1);
      }
    } else if (myData.mainSets[5] == 1) { //倒序
      for (let i=0;i<12;i++) {
        renderGemIcons.push(tempSets[11-i]);
      }
    } else { //顺序
      for (let i=0;i<12;i++) {
        renderGemIcons.push(tempSets);
      }
    }
  }
  setRenderPropIcons() {
    renderPropIcons = new Array();
    renderPropIcons.push(0); //0表示渲染空白图像
    let tempSets = [1,2,3,4,5];
    for (let i=0;i<5;i++) {
      renderPropIcons.push(tempSets);
    }
  }
三、游玩界面渲染
中间部分主要包括提示栏、黑白方格,有时也需要渲染得分提示。
  renderGamePlaying(gameStatus) {
    ctx.globalAlpha = "1";
    //绘制左上角按钮
    this.btnAreaStartUpX1 = widthL;
    this.btnAreaEndUpX1 = this.btnAreaStartUpX1+buttonUpWidth;
    this.btnAreaStartUpX2 = this.btnAreaEndUpX1+2;
    this.btnAreaEndUpX2 = this.btnAreaStartUpX2+buttonUpWidth;
    this.btnAreaStartUpY = widthL;
    this.btnAreaEndUpY = this.btnAreaStartUpY+buttonUpWidth;
    splitWidth = 64;splitHeight = 64;
    ctx.drawImage(buttonUs,2*splitWidth,0*splitHeight,splitWidth,splitHeight,this.btnAreaStartUpX1,this.btnAreaStartUpY,buttonUpWidth,buttonUpWidth);
    ctx.drawImage(buttonUs,3*splitWidth,0*splitHeight,splitWidth,splitHeight,this.btnAreaStartUpX2,this.btnAreaStartUpY,buttonUpWidth,buttonUpWidth);
    //绘制得分
    fontSize = parseInt(blockWidth*0.9);ctx.fillStyle = myData.mainSets[0]==0?'#000':'#fff';ctx.font = fontSize+'px'+fontFamily;
    text = myData.score+"";
    ctx.fillText(text,screenWidth/2-ctx.measureText(text).width/2,heightU);
    //绘制提示栏
    ctx.drawImage(backgroundCU,widthL,heightU+heightCUU,widthCUC,heightCUC);
    let gemsWidth = 128;let gemsHeight = 128;
    let iconsWidth = 64;let iconsHeight = 64;
    for (let i=0;i<myData.playingSets[4];i++) {
      ctx.drawImage(gems,((renderGemColors[myData.newGemColors]-1)%6)*gemsWidth,parseInt((renderGemColors[myData.newGemColors]-1)/6)*gemsHeight,gemsWidth,gemsHeight,widthL+blockWidth*i,heightU+heightCUU,blockWidth,blockWidth);
      ctx.drawImage(icons,((renderGemIcons[myData.newGemIcons]-1)%6)*iconsWidth,parseInt((renderGemIcons[myData.newGemIcons]-1)/6)*iconsHeight,iconsWidth,iconsHeight,widthL+blockWidth*i,heightU+heightCUU,blockWidth,blockWidth);
    }
    fontSize = parseInt(blockWidth*0.8);ctx.fillStyle = '#fff';ctx.font = fontSize+'px'+fontFamily;
    let curTime = "∞";
    if (myData.playingSets[5] > 0) {
      if (gameStatus == "pause") myData.pauseTime = new Date().getTime()-myData.pauseBeginTime;
      else if (myData.pauseTime != 0) {
        myData.beginTime += myData.pauseTime;myData.pauseTime = 0;
      } else myData.deltaTime = new Date().getTime()-myData.beginTime+myData.deltaTime;
      let myTime = myData.playingSets[5] - parseInt(myData.deltaTime/1000);
      if (myTime <= 0) {
        myData.gameOver = true;
        myData.endTime = new Date().getTime();
        return;
      }
      let curTime1 = parseInt(myTime/60);let curTime2 = myTime%60;
      if (curTime1<10) curTime1 = "0"+curTime1;if (curTime2<10) curTime2 = "0"+curTime2;
      curTime = curTime1+":"+curTime2;
    }
    ctx.fillText(curTime,screenWidth/2-ctx.measureText(curTime).width/2,heightU+heightCUU+heightCUC/2);
    splitWidth = 128;splitHeight = 128;
    for (let i=0;i<myData.playingSets[6];i++) {
      let w = myData.propIcons%6;let h = (myData.propIcons-w)/6%1;
      ctx.drawImage(props,w*splitWidth,h*splitHeight,splitWidth,splitHeight,widthL+blockWidth*(6+i),heightU+heightCUU,blockWidth,blockWidth);
    }
    //绘制中间格子和宝石
    ctx.drawImage(backgroundC2,widthL,heightU+heightCU,widthCC,heightCC);
    if (myData.frame%3 == 0) {
      if (myData.pathIndexs.length > 2) {
        myData.gemColors[myData.pathIndexs[myData.pathIndexs.length-2]] = myData.gemColors[myData.pathIndexs[myData.pathIndexs.length-1]];
        myData.gemColors[myData.pathIndexs[myData.pathIndexs.length-1]] = 0;
        myData.pathIndexs.splice(myData.pathIndexs.length-1,1);
      } else if (myData.pathIndexs.length == 2) {
        myMusic.playMoveGem();
        myData.gemColors[myData.pathIndexs[0]] = myData.gemColors[myData.pathIndexs[1]];
        myData.gemColors[myData.pathIndexs[1]] = 0;
        myData.scoreAdd = myData.clearGemsAndSetScore(myData.pathIndexs[0]);
        if (myData.scoreAdd == 0) {
          myData.putGenerateGems();
          oldGemPutIndex = myData.oldGemNextIndexs.length==0?-1:myData.oldGemNextIndexs.length;
        } else {
          curClearHideShowTimes = clearHideShowTimes;
        }
        myData.pathIndexs = new Array();
      }
    }
    if (curClearHideShowTimes != 0) {
      if (myData.frame%6 == 0) {
        for (let i=0;i<myData.allClearIndexs.length;i++) {
          myData.gemColors[myData.allClearIndexs] *= -1;
        }
        curClearHideShowTimes--;
        if (curClearHideShowTimes == 0) {
          for (let i=0;i<myData.allClearIndexs.length;i++) {
            myData.gemColors[myData.allClearIndexs] = 0;
          }
          myMusic.playClearGem();
          myData.allClearIndexs = new Array();
          myData.score += myData.scoreAdd;
          curAddScoreShowTime = scoreAddShowTime;
          curAddScore = myData.scoreAdd;
          myData.scoreAdd = 0;
        }
      }
    } else if (myData.frame%7 == 0 && oldGemPutIndex != -1) {
      myData.gemColors[myData.oldGemNextIndexs[oldGemPutIndex]] = myData.newGemColors[oldGemPutIndex];
      myData.scoreAdd = myData.clearGemsAndSetScore(myData.oldGemNextIndexs[oldGemPutIndex])*2; //一出便消得分*2
      if (myData.scoreAdd != 0) curClearHideShowTimes = clearHideShowTimes;
      oldGemPutIndex--;
      if (oldGemPutIndex == -1) {
        myData.oldGemNextIndexs = new Array();
        myData.newGemColors = new Array();
        myData.generateNewGems();
      }
    }
    this.btnAreaStartCenterX = widthL;
    this.btnAreaEndCenterX = this.btnAreaStartCenterX+widthCC;
    this.btnAreaStartCenterY = heightU+heightCU;
    this.btnAreaEndCenterY = this.btnAreaStartCenterY+heightCC;
    for (let i=0;i<9;i++) {
      for (let j=0;j<9;j++) {
        if (myData.curSelectedIndex == i*9+j && myData.frame%20 > 10) {
          ctx.drawImage(gems,((renderGemColors[myData.gemColors[i*9+j]<0?0:myData.gemColors[i*9+j]]-1)%6)*gemsWidth,parseInt((renderGemColors[myData.gemColors[i*9+j]<0?0:myData.gemColors[i*9+j]]-1)/6)*gemsHeight,gemsWidth,gemsHeight,this.btnAreaStartCenterX+blockWidth*j,this.btnAreaStartCenterY+blockWidth*i-3,blockWidth,blockWidth);
          ctx.drawImage(icons,((renderGemIcons[myData.gemIcons[i*9+j]<0?0:myData.gemIcons[i*9+j]]-1)%6)*iconsWidth,parseInt((renderGemIcons[myData.gemIcons[i*9+j]<0?0:myData.gemIcons[i*9+j]]-1)/6)*iconsHeight,iconsWidth,iconsHeight,this.btnAreaStartCenterX+blockWidth*j,this.btnAreaStartCenterY+blockWidth*i-3,blockWidth,blockWidth);
        } else {
          ctx.drawImage(gems,((renderGemColors[myData.gemColors[i*9+j]<0?0:myData.gemColors[i*9+j]]-1)%6)*gemsWidth,parseInt((renderGemColors[myData.gemColors[i*9+j]<0?0:myData.gemColors[i*9+j]]-1)/6)*gemsHeight,gemsWidth,gemsHeight,this.btnAreaStartCenterX+blockWidth*j,this.btnAreaStartCenterY+blockWidth*i,blockWidth,blockWidth);
          ctx.drawImage(icons,((renderGemIcons[myData.gemIcons[i*9+j]<0?0:myData.gemIcons[i*9+j]]-1)%6)*iconsWidth,parseInt((renderGemIcons[myData.gemIcons[i*9+j]<0?0:myData.gemIcons[i*9+j]]-1)/6)*iconsHeight,iconsWidth,iconsHeight,this.btnAreaStartCenterX+blockWidth*j,this.btnAreaStartCenterY+blockWidth*i,blockWidth,blockWidth);
        }
      }
    }
    //绘制得分提示
    if (curAddScoreShowTime != 0) {
      ctx.globalAlpha = "0.2";
      let tempWidth = 40*4;let tempHeight = 30*4;
      let scoreIndex = parseInt(Math.abs(curAddScore)/myData.playingSets[0]);
      splitWidth = 256;splitHeight = 192;
      let w = scoreIndex%3;let h = (scoreIndex-w)/3%2;
      ctx.drawImage(scores,w*splitWidth,h*splitHeight,splitWidth,splitHeight,screenWidth/2-tempWidth/2,screenHeight/2-tempHeight/2,tempWidth,tempHeight);
      ctx.globalAlpha = "1";
      let numberWidth = 512/4;let numberHeight = 576/3;
      tempWidth = 40;tempHeight = 60;
      let curAddScoreText = Math.abs(curAddScore)+"";
      let readyWidth = screenWidth/2-(curAddScoreText.length+1)/2*tempWidth;
      let temp = curAddScore>0?10:11;
      ctx.drawImage(numbers,(temp%4)*numberWidth,parseInt(temp/4)*numberHeight,numberWidth,numberHeight,readyWidth,screenHeight/2-tempHeight/2,tempWidth,tempHeight);
      for (let i=0;i<curAddScoreText.length;i++) {
        let temp = curAddScoreText.substring(i,i+1);
        ctx.drawImage(numbers,(temp%4)*numberWidth,parseInt(temp/4)*numberHeight,numberWidth,numberHeight,readyWidth+(i+1)*tempWidth,screenHeight/2-tempHeight/2,tempWidth,tempHeight);
      }
      curAddScoreShowTime--;
    }
    //绘制下方的功能按钮
    let deltaButton = (widthCDC - heightCDC*4)/3;
    let widthButton = heightCDC;
    if (deltaButton <= 0) {
      deltaButton = 8;widthButton = (widthCDC - deltaButton*3)/4;
    }
    this.btnAreaStartDownX1 = widthL;
    this.btnAreaEndDownX1 = this.btnAreaStartDownX1+widthButton;
    this.btnAreaStartDownX2 = this.btnAreaEndDownX1+deltaButton;
    this.btnAreaEndDownX2 = this.btnAreaStartDownX2+widthButton;
    this.btnAreaStartDownX3 = this.btnAreaEndDownX2+deltaButton;
    this.btnAreaEndDownX3 = this.btnAreaStartDownX3+widthButton;
    this.btnAreaStartDownX4 = this.btnAreaEndDownX3+deltaButton;
    this.btnAreaEndDownX4 = this.btnAreaStartDownX4+widthButton;
    this.btnAreaStartDownY = heightU+heightCU+heightCC+heightCDU;
    this.btnAreaEndDownY = this.btnAreaStartDownY+widthButton;

    let buttonDownIndexs = new Array();
    if (myData.gameModel == 1) {
      if (myData.userInfo == null) {
        buttonDownIndexs = [11,0,0,0];
        this.btnAreaEndDownX2 = this.btnAreareadyDownX2;
        this.btnAreaEndDownX3 = this.btnAreareadyDownX3;
        this.btnAreaEndDownX4 = this.btnAreareadyDownX4;
      } else {
        buttonDownIndexs = [11,2,0,0];
        this.btnAreaEndDownX3 = this.btnAreareadyDownX3;
        this.btnAreaEndDownX4 = this.btnAreareadyDownX4;
      }
    }
    splitWidth = 128;splitHeight = 128;
    for (let i=0;i<buttonDownIndexs.length;i++) {
      let w = (buttonDownIndexs-1)%6;let h = (buttonDownIndexs-1-w)/6;
      ctx.drawImage(buttonDs,w*splitWidth,h*splitHeight,splitWidth,splitHeight,widthL+widthButton*i+deltaButton*i,this.btnAreaStartDownY,widthButton,widthButton);
    }
  }
四、移动、消除与得分
回复

使用道具 举报

3

主题

7

帖子

16

积分

新手上路

Rank: 1

积分
16
发表于 昨天 13:08 | 显示全部楼层
顶起出售广告位
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|香雨站

GMT+8, 2025-7-2 01:37 , Processed in 0.073014 second(s), 18 queries .

Powered by Discuz! X3.4

© 2001-2013 Comsenz Inc.. 技术支持 by 巅峰设计

快速回复 返回顶部 返回列表