WARNING: THIS SITE IS A MIRROR OF GITHUB.COM / IT CANNOT LOGIN OR REGISTER ACCOUNTS / THE CONTENTS ARE PROVIDED AS-IS / THIS SITE ASSUMES NO RESPONSIBILITY FOR ANY DISPLAYED CONTENT OR LINKS / IF YOU FOUND SOMETHING MAY NOT GOOD FOR EVERYONE, CONTACT ADMIN AT ilovescratch@foxmail.com
Skip to content

Commit 53de01e

Browse files
committed
launch
1 parent 8433cbb commit 53de01e

File tree

2 files changed

+90
-58
lines changed

2 files changed

+90
-58
lines changed

src/pages/pinball/Obstacle.ts

Lines changed: 41 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,44 @@
11
export class Bumper {
2-
render() {
3-
this.ctx.beginPath()
4-
this.ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2)
5-
this.ctx.fillStyle = '#ff6b6b'
6-
this.ctx.fill()
7-
this.ctx.strokeStyle = '#ff4757'
8-
this.ctx.lineWidth = 2
9-
this.ctx.stroke()
2+
x: number
3+
y: number
4+
radius: number
5+
points: number
6+
7+
constructor(x: number, y: number, radius: number, points: number) {
8+
this.x = x
9+
this.y = y
10+
this.radius = radius
11+
this.points = points
12+
}
13+
14+
draw(ctx: CanvasRenderingContext2D) {
15+
ctx.beginPath()
16+
ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2)
17+
ctx.fillStyle = '#ff6b6b'
18+
ctx.fill()
19+
ctx.strokeStyle = '#ff4757'
20+
ctx.lineWidth = 2
21+
ctx.stroke()
22+
}
23+
24+
handleBallCollision(ball: { x: number; y: number; radius: number; vx: number; vy: number }): number {
25+
const dx = ball.x - this.x
26+
const dy = ball.y - this.y
27+
const distance = Math.sqrt(dx * dx + dy * dy)
28+
29+
if (distance < ball.radius + this.radius) {
30+
// Collision response
31+
const angle = Math.atan2(dy, dx)
32+
ball.vx = Math.cos(angle) * 8
33+
ball.vy = Math.sin(angle) * 8
34+
35+
// Move ball out of obstacle
36+
const overlap = ball.radius + this.radius - distance
37+
ball.x += Math.cos(angle) * overlap
38+
ball.y += Math.sin(angle) * overlap
39+
40+
return this.points
41+
}
42+
return 0
1043
}
1144
}

src/pages/pinball/Pinball.ts

Lines changed: 49 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { CurvedSurface } from "./CurvedSurface"
22
import { Rail } from "./Rail"
33
import { SmoothPath } from "./SmoothPath"
4+
import { Bumper } from "./Obstacle"
45

56
type Flipper = {
67
x: number
@@ -9,13 +10,6 @@ type Flipper = {
910
targetAngle: number
1011
}
1112

12-
type Obstacle = {
13-
x: number
14-
y: number
15-
radius: number
16-
points: number
17-
}
18-
1913
export class PinballGame {
2014
canvas: HTMLCanvasElement
2115
ctx: CanvasRenderingContext2D
@@ -35,12 +29,16 @@ export class PinballGame {
3529
right: Flipper
3630
}
3731

38-
obstacles: Array<Obstacle>
32+
obstacles: Array<Bumper>
3933
rails: Array<Rail>
4034
curves: Array<CurvedSurface>
4135
smoothPaths: Array<SmoothPath>
4236

4337
score: number
38+
launching: boolean = false
39+
launchPower: number = 0
40+
maxLaunchPower: number = 30
41+
launchLaneWidth: number = 40
4442

4543
cleanup = new Set<() => void>()
4644
rafId: number | null = null
@@ -52,8 +50,8 @@ export class PinballGame {
5250
this.height = this.canvas.height
5351

5452
this.ball = {
55-
x: this.width / 2,
56-
y: this.height - 100,
53+
x: this.width - 20,
54+
y: this.height - 50,
5755
radius: 8,
5856
vx: 0,
5957
vy: 0,
@@ -67,22 +65,26 @@ export class PinballGame {
6765
}
6866

6967
this.obstacles = [
70-
{ x: 100, y: 200, radius: 20, points: 100 },
71-
{ x: 300, y: 200, radius: 20, points: 100 },
72-
{ x: 200, y: 150, radius: 15, points: 200 },
73-
{ x: 150, y: 300, radius: 25, points: 150 },
74-
{ x: 250, y: 300, radius: 25, points: 150 }
68+
new Bumper(100, 200, 20, 100),
69+
new Bumper(300, 200, 20, 100),
70+
new Bumper(200, 150, 15, 200),
71+
new Bumper(150, 300, 25, 150),
72+
new Bumper(250, 300, 25, 150)
7573
]
7674

7775
this.rails = [
7876
new Rail(50, 150, 150, 200, 12),
79-
new Rail(250, 200, 350, 150, 12)
77+
new Rail(250, 200, 350, 150, 12),
78+
// Launch lane wall
79+
new Rail(this.width - this.launchLaneWidth, this.height, this.width - this.launchLaneWidth, 80, 5)
8080
]
8181

8282
this.curves = [
8383
new CurvedSurface(200, 100, 60, 0, Math.PI, 15), // Half circle at top
8484
new CurvedSurface(100, 400, 40, Math.PI / 4, 3 * Math.PI / 4, 10),
85-
new CurvedSurface(300, 400, 40, Math.PI / 4, 3 * Math.PI / 4, 10)
85+
new CurvedSurface(300, 400, 40, Math.PI / 4, 3 * Math.PI / 4, 10),
86+
// Top right curve to guide ball from launch lane
87+
new CurvedSurface(this.width - 40, 40, 40, 0, Math.PI, 10)
8688
]
8789

8890
this.smoothPaths = [
@@ -115,7 +117,9 @@ export class PinballGame {
115117
}
116118
if (e.key === ' ') {
117119
e.preventDefault()
118-
this.launchBall()
120+
if (this.ball.x > this.width - this.launchLaneWidth && this.ball.y > this.height - 100) {
121+
this.launching = true
122+
}
119123
}
120124
}, { signal: controller.signal })
121125

@@ -126,14 +130,20 @@ export class PinballGame {
126130
if (e.key === 'ArrowRight' || e.key === 'd') {
127131
this.flippers.right.targetAngle = 0
128132
}
133+
if (e.key === ' ') {
134+
if (this.launching) {
135+
this.launching = false
136+
this.launchBall()
137+
}
138+
}
129139
}, { signal: controller.signal })
130140
this.cleanup.add(() => controller.abort())
131141
}
132142

133143
launchBall() {
134-
if (this.ball.y > this.height - 120) {
135-
this.ball.vx = (Math.random() - 0.5) * 4
136-
this.ball.vy = -15
144+
if (this.ball.x > this.width - this.launchLaneWidth && this.ball.y > this.height - 100) {
145+
this.ball.vy = -this.launchPower
146+
this.launchPower = 0
137147
}
138148
}
139149

@@ -163,24 +173,7 @@ export class PinballGame {
163173

164174
// Check obstacle collisions
165175
this.obstacles.forEach(obstacle => {
166-
const dx = this.ball.x - obstacle.x
167-
const dy = this.ball.y - obstacle.y
168-
const distance = Math.sqrt(dx * dx + dy * dy)
169-
170-
if (distance < this.ball.radius + obstacle.radius) {
171-
// Collision response
172-
const angle = Math.atan2(dy, dx)
173-
this.ball.vx = Math.cos(angle) * 8
174-
this.ball.vy = Math.sin(angle) * 8
175-
176-
// Move ball out of obstacle
177-
const overlap = this.ball.radius + obstacle.radius - distance
178-
this.ball.x += Math.cos(angle) * overlap
179-
this.ball.y += Math.sin(angle) * overlap
180-
181-
// Add score
182-
this.score += obstacle.points
183-
}
176+
this.score += obstacle.handleBallCollision(this.ball)
184177
})
185178

186179
// Check rail collisions
@@ -240,8 +233,8 @@ export class PinballGame {
240233
}
241234

242235
resetBall() {
243-
this.ball.x = this.width / 2
244-
this.ball.y = this.height - 100
236+
this.ball.x = this.width - 20
237+
this.ball.y = this.height - 50
245238
this.ball.vx = 0
246239
this.ball.vy = 0
247240
}
@@ -252,15 +245,7 @@ export class PinballGame {
252245
this.ctx.fillRect(0, 0, this.width, this.height)
253246

254247
// Draw obstacles
255-
this.obstacles.forEach(obstacle => {
256-
this.ctx.beginPath()
257-
this.ctx.arc(obstacle.x, obstacle.y, obstacle.radius, 0, Math.PI * 2)
258-
this.ctx.fillStyle = '#ff6b6b'
259-
this.ctx.fill()
260-
this.ctx.strokeStyle = '#ff4757'
261-
this.ctx.lineWidth = 2
262-
this.ctx.stroke()
263-
})
248+
this.obstacles.forEach(obstacle => obstacle.draw(this.ctx))
264249
this.rails.forEach(rail => rail.draw(this.ctx))
265250
this.curves.forEach(curve => curve.draw(this.ctx))
266251
this.smoothPaths.forEach(path => path.draw(this.ctx))
@@ -277,6 +262,17 @@ export class PinballGame {
277262
this.ctx.strokeStyle = '#ff9ff3'
278263
this.ctx.lineWidth = 2
279264
this.ctx.stroke()
265+
266+
// Draw score
267+
this.ctx.fillStyle = '#fff'
268+
this.ctx.font = '24px Arial'
269+
this.ctx.fillText(`Score: ${this.score}`, 20, 40)
270+
271+
// Draw launch power
272+
if (this.launching || this.launchPower > 0) {
273+
this.ctx.fillStyle = '#ff4757'
274+
this.ctx.fillRect(this.width - 30, this.height - 100 - this.launchPower * 3, 20, this.launchPower * 3)
275+
}
280276
}
281277

282278
drawFlipper(flipper: Flipper, isLeft: boolean) {
@@ -294,6 +290,9 @@ export class PinballGame {
294290
}
295291

296292
gameLoop() {
293+
if (this.launching) {
294+
this.launchPower = Math.min(this.launchPower + 0.5, this.maxLaunchPower)
295+
}
297296
this.updateBall()
298297
this.updateFlippers()
299298
this.render()

0 commit comments

Comments
 (0)