a
This commit is contained in:
@@ -0,0 +1,296 @@
|
||||
<!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>
|
||||
@@ -0,0 +1,288 @@
|
||||
<!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;
|
||||
}
|
||||
#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);
|
||||
}
|
||||
/* Poki SDK 要求:防止页面滚动 */
|
||||
body { position: fixed; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="game-container">
|
||||
<canvas id="application"></canvas>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
// ============================================
|
||||
// Poki SDK 集成框架
|
||||
// ============================================
|
||||
class PokiManager {
|
||||
constructor() {
|
||||
this.initialized = false;
|
||||
this.audioEnabled = true;
|
||||
}
|
||||
|
||||
async init() {
|
||||
try {
|
||||
await PokiSDK.init();
|
||||
console.log('✅ Poki SDK 初始化成功');
|
||||
this.initialized = true;
|
||||
|
||||
// 游戏加载完成
|
||||
PokiSDK.gameLoadingFinished();
|
||||
|
||||
// 禁用页面滚动
|
||||
this.disableScroll();
|
||||
} catch (err) {
|
||||
console.warn('⚠️ Poki SDK 初始化失败:', err);
|
||||
this.initialized = false;
|
||||
}
|
||||
}
|
||||
|
||||
disableScroll() {
|
||||
window.addEventListener('keydown', (e) => {
|
||||
if (['ArrowDown', 'ArrowUp', ' '].includes(e.key)) {
|
||||
e.preventDefault();
|
||||
}
|
||||
});
|
||||
window.addEventListener('wheel', (e) => e.preventDefault(), { passive: false });
|
||||
}
|
||||
|
||||
// 游戏开始
|
||||
gameplayStart() {
|
||||
if (this.initialized) {
|
||||
PokiSDK.gameplayStart();
|
||||
}
|
||||
}
|
||||
|
||||
// 游戏暂停/结束
|
||||
gameplayStop() {
|
||||
if (this.initialized) {
|
||||
PokiSDK.gameplayStop();
|
||||
this.showAd();
|
||||
}
|
||||
}
|
||||
|
||||
// 显示广告
|
||||
async showAd() {
|
||||
if (!this.initialized) return;
|
||||
|
||||
try {
|
||||
await PokiSDK.commercialBreak(() => {
|
||||
// 暂停音频
|
||||
this.audioEnabled = false;
|
||||
});
|
||||
// 恢复音频
|
||||
this.audioEnabled = true;
|
||||
} catch (err) {
|
||||
console.warn('广告播放失败:', err);
|
||||
}
|
||||
}
|
||||
|
||||
// 奖励广告
|
||||
async showRewardedAd(size = 'medium') {
|
||||
if (!this.initialized) return false;
|
||||
|
||||
try {
|
||||
const success = await PokiSDK.rewardedBreak({
|
||||
size: size,
|
||||
onStart: () => { this.audioEnabled = false; }
|
||||
});
|
||||
this.audioEnabled = true;
|
||||
return success;
|
||||
} catch (err) {
|
||||
this.audioEnabled = true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================
|
||||
// PlayCanvas 游戏框架
|
||||
// ============================================
|
||||
class GameFramework {
|
||||
constructor() {
|
||||
// 固定竖屏分辨率
|
||||
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.app.setCanvasResolution(pc.RESOLUTION_AUTO);
|
||||
|
||||
// 响应式调整
|
||||
this.resize();
|
||||
window.addEventListener('resize', () => this.resize());
|
||||
|
||||
// Poki 管理器
|
||||
this.poki = new PokiManager();
|
||||
|
||||
// 游戏状态
|
||||
this.state = 'loading'; // loading, menu, playing, paused, gameover
|
||||
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();
|
||||
|
||||
// 初始化 Poki
|
||||
await this.poki.init();
|
||||
|
||||
// 切换到菜单
|
||||
this.showMenu();
|
||||
}
|
||||
|
||||
createScene() {
|
||||
// 创建相机
|
||||
const camera = new pc.Entity('camera');
|
||||
camera.addComponent('camera', {
|
||||
clearColor: new pc.Color(0.04, 0.04, 0.1),
|
||||
projection: pc.PROJECTION_ORTHOGRAPHIC,
|
||||
orthoHeight: this.height / 2
|
||||
});
|
||||
camera.setPosition(0, 0, 10);
|
||||
this.app.root.addChild(camera);
|
||||
this.camera = 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);
|
||||
|
||||
// 创建2D渲染层(用于UI)
|
||||
this.createUI();
|
||||
}
|
||||
|
||||
createUI() {
|
||||
// 由子类实现
|
||||
}
|
||||
|
||||
// 状态切换
|
||||
showMenu() {
|
||||
this.state = 'menu';
|
||||
this.poki.gameplayStop();
|
||||
}
|
||||
|
||||
startGame() {
|
||||
this.state = 'playing';
|
||||
this.score = 0;
|
||||
this.poki.gameplayStart();
|
||||
}
|
||||
|
||||
pauseGame() {
|
||||
if (this.state === 'playing') {
|
||||
this.state = 'paused';
|
||||
this.poki.gameplayStop();
|
||||
}
|
||||
}
|
||||
|
||||
resumeGame() {
|
||||
if (this.state === 'paused') {
|
||||
this.state = 'playing';
|
||||
this.poki.gameplayStart();
|
||||
}
|
||||
}
|
||||
|
||||
gameOver() {
|
||||
this.state = 'gameover';
|
||||
this.poki.gameplayStop();
|
||||
}
|
||||
|
||||
// 工具方法:创建精灵
|
||||
createSprite(name, x, y, width, height, color) {
|
||||
const entity = new pc.Entity(name);
|
||||
entity.addComponent('render', {
|
||||
type: 'plane'
|
||||
});
|
||||
entity.setLocalScale(width, 1, height);
|
||||
entity.setPosition(x, y, 0);
|
||||
|
||||
// 创建材质
|
||||
const material = new pc.StandardMaterial();
|
||||
material.diffuse = color;
|
||||
material.update();
|
||||
entity.render.material = material;
|
||||
|
||||
return entity;
|
||||
}
|
||||
|
||||
// 工具方法:创建文字
|
||||
createText(text, x, y, options = {}) {
|
||||
const entity = new pc.Entity('text');
|
||||
entity.addComponent('element', {
|
||||
type: 'text',
|
||||
text: text,
|
||||
fontSize: options.fontSize || 32,
|
||||
color: options.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)
|
||||
});
|
||||
entity.setPosition(x, y, 0);
|
||||
return entity;
|
||||
}
|
||||
}
|
||||
|
||||
// 启动游戏(由具体游戏实现)
|
||||
// const game = new MyGame();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user