开维游戏引擎(Kaiwei Engine)是基于js设计的跨平台游戏引擎。内核c++编写,v8引擎封装游戏函数,Assembly实现htm跨平台高效运行。
下面以"五子棋"小游戏为例,演示实现过程。
开维游戏引擎js代码跨平台通用,一次编写,多端运行。支持导出exe和网页html,网页使用wasm运行,小游戏运行效率网页版和exe无太大差别,比原生javacript游戏引擎运行速度快数倍。
开维游戏引擎适合AI写小游戏、特效或功能模块。利用AI模型自动生成特效代码,代码短小精炼,函数简单易懂,200行左右即可完成独立功能。导出的html网页可以内嵌到各种网站、安卓苹果手机app中。
开维引擎的底层是C++编写的高性能内核,通过V8引擎封装JavaScript接口,再通过WASM实现网页端高效运行。这意味着,虽然你用的是JavaScript,但实际执行效率远高于普通HTML5游戏引擎(如Phaser),接近原生应用。这一架构决定了它特别适合AI生成代码------因为AI模型只需理解JavaScript API层,无需关心底层C++实现,即可生成可直接运行的高效代码。因此以API为标准,避免参考其他引擎(如Unity或Cocos)的思维模式,否则容易混淆概念。
开维游戏引擎-五子棋
代码如下:
javascript
// 五子棋实例
// AI模型应用:此实例包含几乎所有基本控件函数,可以给AI模型,例如:DeepSeek,Gemini,豆包等
// AI游戏生成:以实例为基础自动生成AI游戏代码,例如贪吃蛇,飞机大战,俄罗斯方块等小游戏
// AI提示文本:"下面是开维游戏引擎的代码演示,根据这个代码,写一个sinx的函数演示代码。 代码如下:(实例代码,可以002游戏登录的代码)"
game.init()
game.setFPS(10);
var window = game.getWindow(); // 获取资源对象
var texture = game.getResource().getTexture("logo.png"); // 获取纹理数据对象
window.setIcon(texture); // 设置主游戏窗口图标
window.setTitle("开维游戏引擎-五子棋");// 设置主游戏窗口标题
new Gobang();
game.run();
// 工具类:生成对象
class Util{
// 函数功能:创建背景场景,并返回场景和背景节点
static bj=(options={})=>{
let w = game.getWindow().getWidth();
let h = game.getWindow().getHeight();
let config = {
x: 0,
y: 0,
width: w,
height: h,
picture: "bg.jpg",
...options
};
// 创建场景
let scene = new Scene();
GlobalVariable.scene = scene;
game.pushScene(scene);
// 添加游戏背景图
const cache_res = game.getResource();
let bg = cache_res.getTexture(config.picture);
const node = new Sprite();
node.setTexture(bg);
node.setSize(config.width,config.height);
node.setPosition(config.x,config.y);
node.setColor(1,1,1,1);
scene.addNode(node);
// 返回场景对象
return {scene:scene,backgroundNode:node};
}
// 函数功能:创建精灵节点,并返回精灵
static newSprite(options={}){
let config = {
x: 0,
y: 0,
width: 50,
height: 30,
clickCb: undefined,
texture: "",
...options
};
if(!GlobalVariable.scene){
// log("scene is not exist");
return;
}
const cache_ = game.getResource();
let bg = cache_.getTexture(config.texture);
let sprite = new Sprite();
sprite.setTexture(bg);
sprite.setSize(config.width, config.height);
sprite.setPosition(config.x, config.y);
GlobalVariable.scene.addNode(sprite);
sprite.click(()=>{
if (config.clickCb !== undefined && config.clickCb instanceof Function){
config.clickCb();
}
});
return sprite;
}
// 函数功能:创建文本节点,并返回文本对象
static newText(options){
// 如果场景不存在,返回
if(!GlobalVariable.scene){
return;
}
// 文本节点参数
let config = {
x: 0,
y: 0,
width: 50,
height: 30,
text: "",
fontSize: 20,
textColor: [1,0,0],
...options
};
// 打印日志,调试用
log(JSON.stringify(config));
// 设置lab标签
const lab = new Label();
lab.setPosition(config.x, config.y);
lab.setSize(config.width, config.height);
lab.setFont("st.ttf", config.fontSize);
lab.setText(config.text);
// 设置颜色
if(config.textColor !== undefined && config.textColor.length === 3){
let configColor = config.textColor;
lab.setTextColor(configColor[0],configColor[1],configColor[2],1);
}else {
lab.setTextColor(1,0,0,1);
}
lab.setColor(1,1,1,0);
GlobalVariable.scene.addNode(lab);
return lab;
}
// 函数功能:获取节点位置和大小
static getPosition(node){
if (!node){
return;
}
let x = node.getPosition().x;
let y = node.getPosition().y;
let width = node.getSize().x;
let height = node.getSize().y;
return {x:x, y:y, width:width, height:height};
}
}
/**
* 五子棋核心逻辑类
*/
class Gobang {
// 棋子精灵对象数组,用于后续悔棋或清空画布
static chessPieces = [];
// 15x15 棋盘状态数组 (0:无子, 1:玩家/黑子, 2:电脑/白子)
static chessBoard = [];
// 赢法三维数组 [x][y][winIndex]
static wins = [];
// 赢法统计数组
static myWin = [];
static computerWin = [];
// 赢法总数
static count = 0;
// 游戏结束标志位
static win = false;
// 棋盘在屏幕上的偏移坐标
static posX = 0;
static posY = 0;
// 当前活动场景引用
static scene;
static audio = new Audio();
constructor() {
Gobang.init();
}
/**
* 初始化游戏环境、棋盘状态及赢法统计
*/
static init() {
// 重置全局与静态状态
GlobalVariable.gameOver = false;
this.win = false;
this.chessBoard = [];
this.chessPieces = [];
this.wins = [];
this.myWin = [];
this.computerWin = [];
// 初始化UI背景
let { scene } = Util.bj({ picture: "mainbg.png" });
this.scene = scene;
let bg = Gobang.createChessBg();
// 注册交互事件:0-下子,1-其他功能
bg.click((type, x, y) => {
if (GlobalVariable.gameOver) return;
if (type === 0) {
this.logic(x, y);
}
});
// 获取棋盘物理坐标起始点
let position = Util.getPosition(bg);
this.posX = position.x;
this.posY = position.y;
// --- 预计算赢法统计 (空间换时间) ---
// 初始化三维赢法空间
for (let i = 0; i < 15; i++) {
this.wins[i] = [];
for (let j = 0; j < 15; j++) {
this.wins[i][j] = [];
}
}
let count = 0;
// 1. 横线赢法
for (let i = 0; i < 15; i++) {
for (let j = 0; j < 11; j++) {
for (let k = 0; k < 5; k++) {
this.wins[i][j + k][count] = true;
}
count++;
}
}
// 2. 竖线赢法
for (let i = 0; i < 15; i++) {
for (let j = 0; j < 11; j++) {
for (let k = 0; k < 5; k++) {
this.wins[j + k][i][count] = true;
}
count++;
}
}
// 3. 正斜线赢法 (\)
for (let i = 0; i < 11; i++) {
for (let j = 0; j < 11; j++) {
for (let k = 0; k < 5; k++) {
this.wins[i + k][j + k][count] = true;
}
count++;
}
}
// 4. 反斜线赢法 (/)
for (let i = 0; i < 11; i++) {
for (let j = 14; j > 3; j--) {
for (let k = 0; k < 5; k++) {
this.wins[i + k][j - k][count] = true;
}
count++;
}
}
this.count = count;
// 初始化每种赢法的达成进度
for (let i = 0; i < count; i++) {
this.myWin[i] = 0;
this.computerWin[i] = 0;
}
// 初始化逻辑棋盘
for (let i = 0; i < 15; i++) {
this.chessBoard[i] = [];
for (let j = 0; j < 15; j++) {
this.chessBoard[i][j] = 0;
}
}
}
/**
* AI 决策逻辑 - 基于分值的启发式算法
* 算法逻辑:遍历棋盘所有空位,计算拦截分(myScore)和进攻分(computerScore),选出最优点。
*/
static computerAI() {
if (GlobalVariable.gameOver) return;
let myScore = [];
let computerScore = [];
let iMax = 0; // 最高评分
let u = 0, v = 0; // 选中的坐标
// 初始化当次评分表
for (let i = 0; i < 15; i++) {
myScore[i] = [];
computerScore[i] = [];
for (let j = 0; j < 15; j++) {
myScore[i][j] = 0;
computerScore[i][j] = 0;
}
}
for (let i = 0; i < 15; i++) {
for (let j = 0; j < 15; j++) {
if (this.chessBoard[i][j] === 0) {
for (let k = 0; k < this.count; k++) {
if (this.wins[i][j][k]) {
// 评估玩家威胁程度 (拦截逻辑)
const playerP = this.myWin[k];
const scoresP = [0, 200, 400, 2000, 10000];
if (playerP < 5) myScore[i][j] += scoresP[playerP] || 0;
// 评估电脑优势程度 (攻击逻辑)
const aiP = this.computerWin[k];
const scoresAI = [0, 400, 800, 2200, 20000];
if (aiP < 5) computerScore[i][j] += scoresAI[aiP] || 0;
}
}
// 择优录取:比较玩家得分,决定是否围堵
if (myScore[i][j] > iMax) {
iMax = myScore[i][j];
u = i; v = j;
} else if (myScore[i][j] === iMax) {
if (computerScore[i][j] > computerScore[u][v]) {
u = i; v = j;
}
}
// 择优录取:比较电脑得分,决定是否进攻
if (computerScore[i][j] > iMax) {
iMax = computerScore[i][j];
u = i; v = j;
} else if (computerScore[i][j] === iMax) {
if (myScore[i][j] > myScore[u][v]) {
u = i; v = j;
}
}
}
}
}
// 执行AI落子
this.createChessPiece(u + 1, v + 1, true);
this.chessBoard[u][v] = 2;
// 更新赢法权重统计
for (let k = 0; k < this.count; k++) {
if (this.wins[u][v][k]) {
this.computerWin[k]++;
this.myWin[k] = 6; // 该赢法路径已被阻塞,设为无效值
if (this.computerWin[k] === 5) {
GlobalVariable.gameOver = true;
this.win = false;
}
}
}
}
/**
* 创建棋盘背景精灵
* @returns {Sprite} 背景精灵对象
*/
static createChessBg() {
let w = game.getWindow().getWidth();
return Util.newSprite({
x: Math.abs(300 - w / 2) + 5,
y: 5,
width: 600,
height: 600,
texture: "gobang.png"
});
}
/**
* 实例化并渲染棋子
* @param {number} row 行号 (1-15)
* @param {number} col 列号 (1-15)
* @param {boolean} isWhite 是否为白棋
*/
static createChessPiece(row, col, isWhite) {
const cache = game.getResource();
let texture = cache.getTexture(isWhite ? "chess_white.png" : "chess_black.png");
let chessPiece = new Sprite();
chessPiece.setTexture(texture);
chessPiece.setSize(25, 25);
// 核心渲染计算:坐标偏移量 + (行列间隔 * 单位长度)
let x = this.posX + 3 + 40.5 * (col - 1);
let y = this.posY + 3 + 40.5 * (row - 1);
chessPiece.setPosition(x, y);
this.scene.addNode(chessPiece);
this.chessPieces.push(chessPiece);
}
/**
* 处理玩家点击落子逻辑
* @param {number} x 点击点绝对横坐标
* @param {number} y 点击点绝对纵坐标
*/
static logic(x, y) {
if (GlobalVariable.gameOver) return;
// 坐标反算:将屏幕坐标转为网格坐标
let col = Math.floor((x - this.posX - 3) / 40.5) + 1;
let row = Math.floor((y - this.posY - 3) / 40.5) + 1;
// 边界防御检查
if (row < 1 || row > 15 || col < 1 || col > 15) return;
if (this.chessBoard[row - 1][col - 1] !== 0) return;
// 玩家落子逻辑
this.createChessPiece(row, col, false);
this.chessBoard[row - 1][col - 1] = 1;
this.audio.playSound("1.wav"); // 播放音效
// 更新赢法权重并检测玩家是否获胜
for (let k = 0; k < this.count; k++) {
if (this.wins[row - 1][col - 1][k]) {
this.myWin[k]++;
this.computerWin[k] = 6; // 阻塞AI在该赢法上的可能性
if (this.myWin[k] === 5) {
GlobalVariable.gameOver = true;
this.win = true;
break;
}
}
}
// 若玩家未胜,触发AI响应
if (!GlobalVariable.gameOver) {
this.computerAI();
}
this.gameEnd();
}
/**
* 结算处理与UI反馈
*/
static gameEnd() {
if (!GlobalVariable.gameOver) return;
let w = game.getWindow().getWidth();
let h = game.getWindow().getHeight();
let msg = this.win ? "游戏结束,胜利!" : "游戏结束,失败!";
Util.newText({
text: msg,
x: w / 3 + 70,
y: 10,
width: 150,
});
// 显示重试按钮
Util.newSprite({
x: w / 2 - 73,
y: h / 2 - 26,
width: 147,
height: 53,
texture: 'restart.png',
clickCb: () => {
new Gobang(); // 重新实例化
}
});
}
}
// 全局类,全局变量和参数
class GlobalVariable{
// 场景
static scene;
// 游戏结束
static gameOver = false;
}
代码功能:
- main.js:游戏初始化,设置背景音乐等
- util.js:公共类,设置文字等
- Gobang.js:五子棋算法
- GlobalVariable.js:全局类,例如键盘码值等
开维游戏引擎代码简单,函数精简,尽量用极少的js脚本实现游戏功能。代码跨平台通用,一次编写,多端运行,可以直接导出生成exe或者html目录直接运行:
开维游戏引擎-五子棋网页版运行
开维游戏引擎下载:
https://www.ikaiwei.com/download/gamejs/kaiwei_gameide_setup.exe
五子棋页面演示:
https://www.ikaiwei.com/gamejs/example/010_Gobang_html/index.html
源码下载:
https://github.com/ctrljshaha/KaiweiEngine