Files
nanocode/happy-games/templates/game-template.html
T
Ubuntu 32b43f85bd a
2026-07-03 16:58:28 +08:00

297 lines
10 KiB
HTML

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<title>{{GAME_TITLE}} | 小游戏中心</title>
<script src="https://game-cdn.poki.com/scripts/v2/poki-sdk.js"></script>
<script src="https://code.playcanvas.com/playcanvas-stable.min.js"></script>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
html, body {
width: 100%;
height: 100%;
overflow: hidden;
background: #0a0a1a;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
touch-action: none;
}
#game-container {
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
}
canvas {
display: block;
box-shadow: 0 0 40px rgba(0, 100, 255, 0.3);
}
</style>
</head>
<body>
<div id="game-container">
<canvas id="application"></canvas>
</div>
<script>
// ============================================
// Poki SDK 管理器 (复用)
// ============================================
class PokiManager {
constructor() {
this.initialized = false;
}
async init() {
try {
await PokiSDK.init();
console.log('✅ Poki SDK 初始化成功');
this.initialized = true;
PokiSDK.gameLoadingFinished();
// 禁用页面滚动
window.addEventListener('keydown', (e) => {
if (['ArrowDown', 'ArrowUp', ' '].includes(e.key)) e.preventDefault();
});
window.addEventListener('wheel', (e) => e.preventDefault(), { passive: false });
} catch (err) {
console.warn('⚠️ Poki SDK 初始化失败:', err);
}
}
gameplayStart() {
if (this.initialized) PokiSDK.gameplayStart();
}
gameplayStop() {
if (this.initialized) PokiSDK.gameplayStop();
}
async showAd() {
if (!this.initialized) return;
try {
await PokiSDK.commercialBreak();
} catch (err) {}
}
async showRewardedAd(size = 'medium') {
if (!this.initialized) return false;
try {
const success = await PokiSDK.rewardedBreak({ size });
return success;
} catch (err) {
return false;
}
}
}
// ============================================
// {{GAME_CLASS_NAME}} 游戏类
// ============================================
class {{GAME_CLASS_NAME}} {
constructor() {
// 画布尺寸 (统一 480x640 竖屏)
this.width = 480;
this.height = 640;
// 初始化 PlayCanvas
this.canvas = document.getElementById('application');
this.app = new pc.Application(this.canvas, {
mouse: new pc.Mouse(this.canvas),
touch: new pc.TouchDevice(this.canvas),
elementInput: new pc.ElementInput(this.canvas)
});
this.app.start();
this.app.setCanvasFillMode(pc.FILLMODE_NONE);
this.resize();
window.addEventListener('resize', () => this.resize());
// Poki SDK
this.poki = new PokiManager();
// 游戏状态: loading, menu, playing, paused, gameover
this.gameState = 'loading';
this.score = 0;
// 初始化
this.init();
}
resize() {
const container = document.getElementById('game-container');
const aspect = this.width / this.height;
const containerAspect = container.clientWidth / container.clientHeight;
let canvasWidth, canvasHeight;
if (containerAspect > aspect) {
canvasHeight = container.clientHeight;
canvasWidth = canvasHeight * aspect;
} else {
canvasWidth = container.clientWidth;
canvasHeight = canvasWidth / aspect;
}
this.canvas.style.width = canvasWidth + 'px';
this.canvas.style.height = canvasHeight + 'px';
this.app.resizeCanvas(canvasWidth, canvasHeight);
}
async init() {
this.createScene();
this.createMaterials();
await this.poki.init();
this.createUI();
this.setupInput();
this.startGame();
this.app.on('update', (dt) => this.update(dt));
}
createScene() {
// 相机 - 正交投影适配2D游戏
this.camera = new pc.Entity('camera');
this.camera.addComponent('camera', {
clearColor: new pc.Color(0.04, 0.04, 0.1), // 深蓝背景
projection: pc.PROJECTION_ORTHOGRAPHIC,
orthoHeight: this.height / 2
});
this.camera.setPosition(0, 0, 10);
this.app.root.addChild(this.camera);
// 灯光
const light = new pc.Entity('light');
light.addComponent('light', {
type: 'directional',
color: new pc.Color(1, 1, 1),
intensity: 1
});
light.setEulerAngles(45, 30, 0);
this.app.root.addChild(light);
// 游戏根节点
this.gameRoot = new pc.Entity('gameRoot');
this.app.root.addChild(this.gameRoot);
// UI根节点
this.uiRoot = new pc.Entity('uiRoot');
this.app.root.addChild(this.uiRoot);
}
createMaterials() {
// 在这里创建游戏所需材质
this.materials = {};
// 示例:白色材质
this.materials.white = new pc.StandardMaterial();
this.materials.white.diffuse = new pc.Color(1, 1, 1);
this.materials.white.update();
}
createUI() {
// 创建UI元素
// 使用 createText 方法创建文字
this.scoreText = this.createText('💎 得分: 0', 0, this.height/2 - 40, 24);
this.uiRoot.addChild(this.scoreText);
}
createText(text, x, y, fontSize) {
const entity = new pc.Entity('text');
entity.setPosition(x, y, 10);
entity.addComponent('element', {
type: 'text',
text: text,
fontSize: fontSize,
color: new pc.Color(1, 1, 1),
anchor: new pc.Vec4(0.5, 0.5, 0.5, 0.5),
pivot: new pc.Vec2(0.5, 0.5)
});
return entity;
}
setupInput() {
// 鼠标输入
this.app.mouse.on(pc.EVENT_MOUSEDOWN, (e) => this.onPointerDown(e.x, e.y));
this.app.mouse.on(pc.EVENT_MOUSEMOVE, (e) => this.onPointerMove(e.x, e.y));
this.app.mouse.on(pc.EVENT_MOUSEUP, () => this.onPointerUp());
// 触摸输入
this.app.touch.on(pc.EVENT_TOUCHSTART, (e) => {
const touch = e.touches[0];
this.onPointerDown(touch.x, touch.y);
});
this.app.touch.on(pc.EVENT_TOUCHMOVE, (e) => {
const touch = e.touches[0];
this.onPointerMove(touch.x, touch.y);
});
this.app.touch.on(pc.EVENT_TOUCHEND, () => this.onPointerUp());
}
onPointerDown(screenX, screenY) {
// 处理按下事件
}
onPointerMove(screenX, screenY) {
// 处理移动事件
}
onPointerUp() {
// 处理释放事件
}
screenToWorld(screenX, screenY) {
const rect = this.canvas.getBoundingClientRect();
const x = (screenX - rect.left) / rect.width * this.width - this.width / 2;
const y = this.height / 2 - (screenY - rect.top) / rect.height * this.height;
return { x, y };
}
startGame() {
this.gameState = 'playing';
this.poki.gameplayStart();
}
pauseGame() {
if (this.gameState === 'playing') {
this.gameState = 'paused';
this.poki.gameplayStop();
}
}
resumeGame() {
if (this.gameState === 'paused') {
this.gameState = 'playing';
this.poki.gameplayStart();
}
}
gameOver() {
this.gameState = 'gameover';
this.poki.gameplayStop();
this.poki.showAd();
// 显示游戏结束UI
}
restart() {
this.score = 0;
this.startGame();
}
update(dt) {
// 游戏主循环
if (this.gameState !== 'playing') return;
// 在这里更新游戏逻辑
}
updateUI() {
this.scoreText.element.text = `💎 得分: ${this.score}`;
}
}
// 启动游戏
const game = new {{GAME_CLASS_NAME}}();
</script>
</body>
</html>