|
@@ -2,8 +2,8 @@
|
|
|
<div class="game-container">
|
|
|
<canvas id="canvas" @mousedown="handleMouseDown" @mouseup="handleMouseUp" @touchstart="handleTouchStart"
|
|
|
@touchend="handleTouchEnd"></canvas>
|
|
|
- <canvas ref="canvasRef" :width="clientObj.width" :height="clientObj.height"
|
|
|
- style="position:fixed;left: 0; top: 0;"></canvas>
|
|
|
+ <!-- <canvas ref="canvasRef" :width="clientObj.width" :height="clientObj.height"
|
|
|
+ style="position:fixed;left: 0; top: 0;"></canvas> -->
|
|
|
</div>
|
|
|
</template>
|
|
|
|
|
@@ -288,7 +288,6 @@ const getCanvas = () => {
|
|
|
|
|
|
// 游戏主类的响应式状态
|
|
|
const gameState = reactive({
|
|
|
- version: '0.1',
|
|
|
balls: [],
|
|
|
hoops: [],
|
|
|
texts: [],
|
|
@@ -296,8 +295,8 @@ const gameState = reactive({
|
|
|
score: 0,
|
|
|
started: false,
|
|
|
gameOver: false,
|
|
|
- ballX: 320 / 2,
|
|
|
- ballY: 880,
|
|
|
+ ballX: (640 - 93) / 2, // 篮球初始X坐标(居中)
|
|
|
+ ballY: 880, // 篮球初始Y坐标(底部)
|
|
|
ballVel: 300,
|
|
|
ballAngleVel: 100,
|
|
|
ballAngle: 0,
|
|
@@ -399,9 +398,9 @@ class Ball {
|
|
|
this.falling = true;
|
|
|
}
|
|
|
|
|
|
- if (this.x + 47 > 640) {
|
|
|
+ if (this.x + 47 > clientObj.value.width) {
|
|
|
this.vx = this.vx * -1;
|
|
|
- this.x = 640 - 47;
|
|
|
+ this.x = clientObj.value.width - 47;
|
|
|
}
|
|
|
|
|
|
if (this.x - 47 < 0) {
|
|
@@ -483,7 +482,7 @@ const handleTouchEnd = () => {
|
|
|
// 键盘事件处理函数
|
|
|
const handleKeyDown = (event: KeyboardEvent) => {
|
|
|
if (gameState.state !== 'play') return;
|
|
|
-
|
|
|
+
|
|
|
if (event.key === 'ArrowLeft') {
|
|
|
gameState.keyLeft = true;
|
|
|
} else if (event.key === 'ArrowRight') {
|
|
@@ -507,27 +506,27 @@ const handleKeyUp = (event: KeyboardEvent) => {
|
|
|
// 游戏方法
|
|
|
const setupCanvas = () => {
|
|
|
gameState.canvas = document.getElementById('canvas');
|
|
|
- gameState.canvas.width = 640;
|
|
|
- gameState.canvas.height = 960;
|
|
|
+ gameState.canvas.width = clientObj.value.width;
|
|
|
+ gameState.canvas.height = clientObj.value.height;
|
|
|
// gameState.canvas.width = document.documentElement.clientWidth / 2;
|
|
|
// gameState.canvas.height = document.documentElement.clientHeight;
|
|
|
gameState.ctx = gameState.canvas.getContext('2d');
|
|
|
};
|
|
|
|
|
|
const resizeToWindow = () => {
|
|
|
- const w = gameState.canvas.width / gameState.canvas.height;
|
|
|
- const h = window.innerHeight;
|
|
|
- const ratio = h * w;
|
|
|
- gameState.canvas.style.width = Math.floor(ratio) + 'px';
|
|
|
- gameState.canvas.style.height = Math.floor(h) + 'px';
|
|
|
+ // const w = gameState.canvas.width / gameState.canvas.height;
|
|
|
+ // const h = window.innerHeight;
|
|
|
+ // const ratio = h * w;
|
|
|
+ // gameState.canvas.style.width = Math.floor(ratio) + 'px';
|
|
|
+ // gameState.canvas.style.height = Math.floor(h) + 'px';
|
|
|
};
|
|
|
|
|
|
const drawLoadingScreen = () => {
|
|
|
const ctx = gameState.ctx;
|
|
|
ctx.fillStyle = 'black';
|
|
|
- ctx.fillRect(0, 0, 960, 640);
|
|
|
+ ctx.fillRect(0, 0, 960, clientObj.value.width);
|
|
|
ctx.textAlign = 'center';
|
|
|
- drawText(ctx, 'Loading...', 640 / 2, 960 / 2, 40);
|
|
|
+ drawText(ctx, 'Loading...', clientObj.value.width / 2, 960 / 2, 40);
|
|
|
ctx.textAlign = 'left';
|
|
|
};
|
|
|
|
|
@@ -617,9 +616,9 @@ const update = (delta) => {
|
|
|
if (gameState.state === 'play') {
|
|
|
// // 更新篮球横向移动
|
|
|
// gameState.ballX += gameState.ballVel * delta;
|
|
|
- // if (gameState.ballX > 640 - 93) {
|
|
|
+ // if (gameState.ballX > clientObj.value.width - 93) {
|
|
|
// gameState.ballVel = -gameState.ballVel;
|
|
|
- // gameState.ballX = 640 - 93;
|
|
|
+ // gameState.ballX = clientObj.value.width - 93;
|
|
|
// }
|
|
|
// if (gameState.ballX < 0) {
|
|
|
// gameState.ballVel = -gameState.ballVel;
|
|
@@ -633,10 +632,10 @@ const update = (delta) => {
|
|
|
if (gameState.keyRight) {
|
|
|
gameState.ballX += gameState.ballVel * delta;
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
// 边界检查
|
|
|
- if (gameState.ballX > 640 - 93) {
|
|
|
- gameState.ballX = 640 - 93;
|
|
|
+ if (gameState.ballX > clientObj.value.width - 93) {
|
|
|
+ gameState.ballX = clientObj.value.width - 93;
|
|
|
}
|
|
|
if (gameState.ballX < 0) {
|
|
|
gameState.ballX = 0;
|
|
@@ -762,21 +761,44 @@ const draw = () => {
|
|
|
if (!ctx) return;
|
|
|
|
|
|
// 绘制背景
|
|
|
- if (gameState.res['/static/images/basketball/background.png']) {
|
|
|
- ctx.drawImage(gameState.res['/static/images/basketball/background.png'], 0, 0);
|
|
|
+if (gameState.res['/static/images/basketball/background.png']) {
|
|
|
+ const img = gameState.res['/static/images/basketball/background.png'];
|
|
|
+ const canvasWidth = gameState.canvas.width;
|
|
|
+ const canvasHeight = gameState.canvas.height;
|
|
|
+
|
|
|
+ // 计算图片与画布的比例
|
|
|
+ const imgRatio = img.width / img.height;
|
|
|
+ const canvasRatio = canvasWidth / canvasHeight;
|
|
|
+
|
|
|
+ let drawWidth, drawHeight, drawX = 0, drawY = 0;
|
|
|
+
|
|
|
+ // 根据比例计算绘制尺寸
|
|
|
+ if (canvasRatio > imgRatio) {
|
|
|
+ // 画布更宽,按宽度缩放,高度可能超出
|
|
|
+ drawWidth = canvasWidth;
|
|
|
+ drawHeight = canvasWidth / imgRatio;
|
|
|
+ drawY = (canvasHeight - drawHeight) / 2; // 垂直居中
|
|
|
+ } else {
|
|
|
+ // 画布更高,按高度缩放,宽度可能超出
|
|
|
+ drawHeight = canvasHeight;
|
|
|
+ drawWidth = canvasHeight * imgRatio;
|
|
|
+ drawX = (canvasWidth - drawWidth) / 2; // 水平居中
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
+ // 绘制图片(可能裁剪边缘)
|
|
|
+ ctx.drawImage(img, drawX, drawY, drawWidth, drawHeight);
|
|
|
+}
|
|
|
// 绘制菜单状态
|
|
|
if (gameState.state === 'menu') {
|
|
|
if (gameState.res['/static/images/basketball/title.png']) {
|
|
|
ctx.drawImage(
|
|
|
gameState.res['/static/images/basketball/title.png'],
|
|
|
- 640 / 2 - (492 / 2),
|
|
|
+ clientObj.value.width / 2 - (492 / 2),
|
|
|
100
|
|
|
);
|
|
|
}
|
|
|
ctx.textAlign = 'center';
|
|
|
- drawText(ctx, '请做投篮动作开始游戏', 640 / 2, 520, 40);
|
|
|
+ drawText(ctx, '请做投篮动作开始游戏', clientObj.value.width / 2, 520, 40);
|
|
|
}
|
|
|
|
|
|
// 绘制游戏状态
|
|
@@ -821,9 +843,9 @@ const draw = () => {
|
|
|
// 绘制游戏结束界面
|
|
|
if (gameState.state === 'over') {
|
|
|
ctx.textAlign = 'center';
|
|
|
- drawText(ctx, 'Game Over', 640 / 2, 200, 80);
|
|
|
- drawText(ctx, 'Score: ' + gameState.score, 640 / 2, 400, 50);
|
|
|
- drawText(ctx, 'Click to Continue', 640 / 2, 800, 50);
|
|
|
+ drawText(ctx, 'Game Over', clientObj.value.width / 2, 200, 80);
|
|
|
+ drawText(ctx, 'Score: ' + gameState.score, clientObj.value.width / 2, 400, 50);
|
|
|
+ drawText(ctx, 'Click to Continue', clientObj.value.width / 2, 800, 50);
|
|
|
ctx.textAlign = 'center';
|
|
|
}
|
|
|
};
|
|
@@ -843,8 +865,8 @@ const initGame = async () => {
|
|
|
// 添加篮筐
|
|
|
gameState.hoops = [
|
|
|
new Hoop(110, 520),
|
|
|
- new Hoop(640 - 148 - 110, 520),
|
|
|
- new Hoop(640 / 2 - (148 / 2), 260)
|
|
|
+ new Hoop(clientObj.value.width - 148 - 110, 520),
|
|
|
+ new Hoop(clientObj.value.width / 2 - (148 / 2), 260)
|
|
|
];
|
|
|
|
|
|
// 开始游戏循环
|