2024年全球 MoonBit 编程创新赛-零基础早鸟教程-使用wasm4八小时开发井子棋小游戏

在这里插入图片描述

前言

  • 本篇文章主要分享 “2024年全球 MoonBit 编程创新赛 游戏赛道”参赛过程中九宫棋游戏的开发技巧和心得。以此抛砖引玉。首先介绍下 MoonBit。

  • 月兔语言 MoonBit 是一个用于云计算和边缘计算的 WebAssembly 端到端的编程语言工具链。 您可以访问 https://try.moonbitlang.cn 获得 IDE 环境,无需安装任何软件,也不依赖任何服务器。生成比现有解决方案明显体积更小的 WASM 文件。并有着更高的运行时性能和先进的编译时性能

  • 比赛会用到 WASM-4 引擎,此引擎是一个框架,可以开发有趣的复古游戏,最终的编译文件可在浏览器或单片机设备(如 ESP32)上直接运行。

话不多说,直入正题

开发环境准备

  • 拢共分为5步, 我们目标是以最快速度进入到游戏开发本身。因此略过目录,配置等说明,可通过官网了解更多细节。

1. 部署月兔环境

curl -fsSL https://cli.moonbitlang.cn/install/unix.sh | bash

2. 创建项目工作区

mkdir moonbit_wsam4_game
cd moonbit_wsam4_game
moon new --lib --path . --user spaceack --name mygame

3. 安装wasm4依赖

npm install -D wasm4 

4. 将 wasm4绑定增加到项目中

moon update && moon add moonbitlang/wasm4

在这里插入图片描述
此时的代码目录如下:
在这里插入图片描述

5. 更新项目配置

  1. 使用以下代码覆盖 moon.pkg.json文件
{// "is-main": true,"import": ["moonbitlang/wasm4"],"link": {"wasm-gc": {"exports": ["start", "update"],"import-memory": {"module": "env","name": "memory"}},"wasm": {"exports": ["start", "update"],"import-memory": {"module": "env","name": "memory"},"heap-start-address": 6590}}
}
  1. 使用以下代码覆盖top.mbt文件
pub fn update() -> Unit {}
pub fn start() -> Unit {}

编译及运行

  • 此时一个游戏代码已经写好了,我们编译并运行看看效果
# 编译
moon build --target wasm
# 运行npx wasm4 run target/wasm/release/build/mygame.wasm

在这里插入图片描述

  • 访问 http://localhost:4444 即可查看执行效果。可见绿油油的一片。 这是WASM-4 引擎的默认配色。
    在这里插入图片描述

游戏开发

小试牛刀

  • top.mbt文件是游戏的主程序的入口, 简单逻辑的游戏,所有逻辑仅在此文件内编写即可。

  • 依据惯例,首先我们尝试在终端打印“Hello, World”。在start()函数中调用wasm的trace方法即可。它可是我们调试程序的好帮手。😊

pub fn update() -> Unit {}
pub fn start() -> Unit {
@wasm4.trace("Hello world!");
}
  • 太好啦,经过再次编译运行,我们的代码起作用啦,在终端成功打印了Hello World.
    在这里插入图片描述

设置配色

  • wasm 单帧最多支持4种颜色,可以对调色板的4个颜色索引设置配色。这里我们要用到set_palette方法。 默认索引1为背景色。
pub fn start() -> Unit {@wasm4.trace("Hello world!");@wasm4.set_palette(1, @wasm4.rgb(0x282e30)) // 暗岩灰@wasm4.set_palette(2, @wasm4.rgb(0xaa337f)) // 陈玫红 Maximum Red Purple@wasm4.set_palette(3, @wasm4.rgb(0xd4392e)) // 茜红@wasm4.set_palette(4, @wasm4.rgb(0x898f92)) // 
}
  • 太好啦,经过再次编译运行,我们的代码起作用啦,背景色成功变为了暗岩灰。

绘制图形

  • wasm 界面的长和宽是固定的 160*160像素
  • 以左上为坐标0点(第三象限)
  • wasm支持绘制矩形,椭圆, 线等基础图形。复杂的图形由基础图形构成,
    可练习实现如下效果图:
    在这里插入图片描述
    代码如下:
pub fn update() -> Unit {@wasm4.set_draw_colors(2) // 选用调色板索引为2的颜色,即茜红 @wasm4.rect(0, 0, 80, 80) // 用茜红绘制一个矩阵 四个参数分别为第三象限的 x, y, width, heigh@wasm4.set_draw_colors(4) @wasm4.line(0, 0, 80, 80)   //一条斜线 从左上到中间(叠加到矩形之上)@wasm4.line(0, 80, 160, 80) // 中间一条横线 (叠加到矩形之上)@wasm4.line(80, 0, 80, 160) // 中间一条竖	线 (叠加到矩形之上)@wasm4.set_draw_colors(3) @wasm4.oval(80, 80, 80,80 ) // 圆 第四象限
} 
pub fn start() -> Unit {@wasm4.trace("Hello world!");@wasm4.set_palette(1, @wasm4.rgb(0xaa337f)) // 陈玫红 Maximum Red Purple@wasm4.set_palette(2, @wasm4.rgb(0xd4392e)) // 茜红@wasm4.set_palette(3, @wasm4.rgb(0xffffff)) // 白@wasm4.set_palette(4, @wasm4.rgb(0x282e30)) // 暗岩灰
}

游戏状态

在这里插入图片描述

  • 一般游戏可以抽象为一个状态机,总共有开始游戏中结束三种基本状态。那么我们需要构建一个状态结构来描绘游戏的状态信息。
  • 以井子棋游戏为例。我们用枚举类型描绘三种状态。并定义一个状态结构来存储状态信息。
  • 这里我们能领略到 MoonBit 简单且实用数据导向语言设计的魅力。
enum GameState {GSInit // 初始状态GSGameStart // 游戏中GSGameEnd // 游戏结束
}struct GameStat {mut game_state : GameState mut score : UInt // 胜利得分mut times: UInt //游戏次数gamemap : FixedArray[FixedArray[Char]] //地图mut player_x : Int mut player_y : Intmut win: String mut step: Intrng : @random.Rand
}
  • 三子棋逻辑并不复杂,至多9个变量就可以描述整个状态!

  • 然后我们使用 let 声明一个名为 gs 的变量, 并将其初始化为 GameStat 类型的一个新实例。

let gs : GameStat = GameStat::new()
pub fn GameStat::new() -> GameStat {let gamemap : FixedArray[FixedArray[Char]] = [['0', '0', '0'],['0', '0', '0'],['0', '0', '0'],]{game_state: GSInit,score: 0,times: 1,gamemap,player_x: 1,player_y: 1,win: "",step: 0,rng: @random.new(),}
}

定义动作(玩家落子,玩家移动,AI落子策略)

  • 有了前面的状态定义,我们可以围绕这些状态参数定义一些动作。
举例1:玩家落子过程
  • 地图中地图使用0表示无棋子, 1代表玩家棋子,那么我们可以写一个函数描述落子过程。
pub fn put_point(self : GameStat) -> Unit {if self.gamemap[self.player_x][self.player_y] == '0' {self.gamemap[self.player_x][self.player_y] = '1'}
}
举例2:玩家移动过程
  • player_xplayer_y 代表玩家坐标。我们可以定义一个左移的过程。
pub fn moveLeft(self : GameStat) -> Unit {if self.player_x > 0 {self.player_x = self.player_x - 1}
}
举例3:AI落子策略
  • 为了降低游戏难度,并没有使用复杂的落子策略。而是利用随机数进行随机落子。
  • 需要注意,随机坐标可能会与玩家落子点坐标重合,避免坐标重合的方法由很多种,这里使用循环检测的方式生成唯一的坐标。首先随机生成两个坐标,如果坐标点位置不为空则再次调用生成坐标的函数,直到生成两个不同的坐标。
let mut flag = true
while flag {let limit = 3let x = self.rng.int(~limit)let y = self.rng.int(~limit)if self.gamemap[x][y] == '0' {self.gamemap[x][y] = '2'self.step = self.step + 1flag = false}
}

该篇程序涉及没有复杂的算法,仅使用简单的顺序判断循环 语句和一就可实现稍稍复杂的小游戏。

正所谓:大道至简 重剑无锋 大巧不工


如果此篇文章对您有所帮助,欢迎👏Star 仓库,为我投票,您的支持是我持续更新文章的动力💪,感谢感谢 。仓库链接:https://github.com/spaceack/MoonBit-Code-JAM-2024


竞赛地址:https://tianchi.aliyun.com/competition/entrance/532262

在线试玩链接:https://moonbitlang.github.io/MoonBit-Code-JAM-2024/CS%E8%B5%8F%E9%87%91%E7%8C%8E%E6%89%8B/index.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/457168.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

文本预处理操作简述

自然语言处理 (NLP) 是数据科学的一个分支,主要处理文本数据。除了数值数据外,文本数据也广泛可用,用于分析和解决业务问题。然而,在使用数据进行分析或预测之前,处理数据非常重要。 我们执行文本预处理来准备用于模型…

mysql的卸载与安装

一、mysql的卸载 1、用管理员模式的打开cmd,我的服务名是mysql。 net stop 【你的服务名】 sc delete 【你的服务名】 2、将下图中有包含‘bin’目录,‘data’目录等等的这个总目录删掉 如图我的目录是:mysql-5.7.28-winx64 3、删除mysql的隐…

代码随想录算法训练营Day39 | 卡玛网-46.携带研究材料、416. 分割等和子集

目录 卡玛网-46.携带研究材料 416. 分割等和子集 卡玛网-46.携带研究材料 题目 卡玛网46. 携带研究材料(第六期模拟笔试) 题目描述: 小明是一位科学家,他需要参加一场重要的国际科学大会,以展示自己的最新研究成…

day3:管道,解压缩,vim

一,管道(|) 引入 当我们要将本次命令结果作为下次命令参数时就可以用到,极大的简化了操作。 比如:head -5 文件| tail -1:表示显示第五行这就是管道的魅力 概述 管道符:| 作用&#xff1a…

【论文阅读】ESRGAN+

学习资料 论文题目:进一步改进增强型超分辨率生成对抗网络(ESRGAN : FURTHER IMPROVING ENHANCED SUPER-RESOLUTION GENERATIVE ADVERSARIAL NETWORK)论文地址:2001.08073代码:ncarraz/ESRGANplus: ICASSP …

Android中的epoll机制

深入理解Android中的epoll机制 在Android系统中,epoll广泛用于高效管理网络和文件的I/O操作。它通过减少CPU资源消耗和避免频繁的内核态-用户态切换,实现了在多连接、多任务环境中的高性能。epoll的特性使其非常适合Android系统中网络服务器、Socket通信…

Android 15自定义设置导航栏与状态栏,EdgeToEdge适配

背景:android api 35,activity设置EdgeToEdge.enable((ComponentActivity) this)前提下 一、设置导航栏与状态栏颜色 设置的状态栏颜色,只需要设置fitsSystemWindows跟setOnApplyWindowInsetsListener xml设置: 代码:…

比例数据可视化(Python实现板块层级图绘制)——Instacart Market Basket Analysis

【实验名称】 实验一:绘制板块层级图 【实验目的】 1. 掌握数据文件读取 2. 掌握数据处理的方法 3. 实现板块层级图的绘制 【数据介绍】Instacart Market Basket Analysis 1. 数据说明 数据共有300 0000orders, 20 0000users, …

logback日志脱敏后异步写入文件

大家项目中肯定都会用到日志打印,目的是为了以后线上排查问题方便,但是有些企业对输出的日志包含的敏感(比如:用户身份证号,银行卡号,手机号等)信息要进行脱敏处理。 哎!我们最近就遇到了日志脱敏的改造。可…

使用text-embedding-3-small生成向量并将向量插入Mlivus Cloud用于语义搜索的深度解析与实战操作

使用text-embedding-3-small生成向量并将向量插入Mlivus Cloud用于语义搜索的深度解析与实战操作 在当今的大数据时代,文本数据的处理与分析显得尤为重要。如何高效地存储、查询和理解这些海量文本数据,成为了许多企业和研究机构面临的重大挑战。幸运的是,随着向量数据库技…

校园表白墙源码修复版

此校园表白墙源码基于thinkphp,因为时代久远有不少bug,经本人修复已去除大部分bug,添加了美化元素。 https://pan.quark.cn/s/1f9b3564c84b https://pan.baidu.com/s/1bb9vu9VV2jJoo9-GF6W3xw?pwd7293 https://caiyun.139.com/m/i?2hoTc…

用更多的钱买电脑而不是手机

如果,我们对自己的定义是知识工作者,那么在工作、学习相关的电子设备投入上,真的别舍不得花钱。 需要留意的是,手机,对于大部分在电脑前工作的人,不是工作设备。在我看来,每年投入到电脑的钱&…

【Java】java 集合框架(详解)

📃个人主页:island1314 ⛺️ 欢迎关注:👍点赞 👂🏽留言 😍收藏 💞 💞 💞 1. 概述 🚀 🔥 Java集合框架 提供了一系列用于存储和操作…

GeoWebCache1.26调用ArcGIS切片

常用网址: GeoServer GeoWebCache (osgeo.org) GeoServer 用户手册 — GeoServer 2.20.x 用户手册 一、版本需要适配:Geoserver与GeoWebCache、jdk等的版本适配对照 ​ 查看来源 二、准备工作 1、数据:Arcgis标准的切片,通过…

前OpenAI首席技术官为新AI初创公司筹资;我国发布首个应用临床眼科大模型 “伏羲慧眼”|AI日报

文章推荐 2024人工智能报告.zip |一文迅速了解今年的AI界都发生了什么? 今日热点 据报道,前OpenAI首席技术官Mira Murati正在为一家新的AI初创公司筹集资金 据路透社报道,上个月宣布离职的OpenAI首席技术官Mira Murati正在为一…

2024年妈杯MathorCup大数据竞赛A题超详细解题思路

2024年妈杯大数据竞赛初赛整体难度约为0.6个国赛。A题为台风中心路径相关问题,为评价预测问题;B题为库存和销量的预测优化问题。B题难度稍大于A题,可以根据自己队伍情况进行选择。26日早六点之前发布AB两题相关解题代码论文。 下面为大家带来…

excel斜线表头

检验数据验证对象 鼠标放在检验数据 验证对象中间,altenter 之后空格 选中格子,右键单元格格式, 完成 如果是需要多分割,操作一样,在画斜线的时候会有区别,在插入里面用直线画斜线即可 在表格插入的时…

el-table相关的功能实现

1. 表格嵌套表格时&#xff0c;隐藏父表格的全选框 场景&#xff1a;当table表格设置复选&#xff08;多选&#xff09;功能时&#xff0c;如何隐藏表头的复选框&#xff0c;不让用户一键多选。 <el-table :header-cell-class-name"cellClass">// 表头复选框禁…

基于Springboot无人驾驶车辆路径规划系统(源码+定制+开发)

博主介绍&#xff1a; ✌我是阿龙&#xff0c;一名专注于Java技术领域的程序员&#xff0c;全网拥有10W粉丝。作为CSDN特邀作者、博客专家、新星计划导师&#xff0c;我在计算机毕业设计开发方面积累了丰富的经验。同时&#xff0c;我也是掘金、华为云、阿里云、InfoQ等平台…

雷赛L6N伺服驱动器基本参数设置——EtherCAT 总线型

1、指令脉冲设置 PA0.08代表电机转一圈&#xff0c;所需要的指令脉冲数&#xff0c;该值驱动器默认值为0&#xff0c;该值更改后断电重启后生效。 2、编码器反馈脉冲设置 PA0.11&#xff0c;代表编码器输出每转脉冲数&#xff0c;实际反馈的脉冲数做了4倍频处理&#xff0c;设…