Read the original article:Building Space Shooter with ArkTS-3
Introduction
Hello, everybody. We have implemented most parts of our application in previous parts. In this part, we will learn how to move our ship. If you haven't seen previous parts, check them here. Part 1 - Part 2
Time to show our moves.
Move
We will move our ship in the horizontal direction.
- Modify the ship.
moveRL(val: number) {
this.leftTop.x = Math.max(
0, Math.min(this.canvasWidth - this.pixelSize * 5, this.leftTop.x + val)
)
}
- Now the
Index.ets. We will add the crown gesture. This requires a real device, but don't worry. I got you.
@Entry
@Component
struct Index {
@State game: Game = new Game()
build() {
Stack() {
...
}
.onDigitalCrown((event: CrownEvent) => {
this.game.userShip?.moveRL(event.degree / 2)
})
}
}
- Let's also add a touch gesture to move our ship. We will divide the page vertically into two parts, and each part will move the ship in its respective direction.
import Game from '../viewmodel/Game'
@Entry
@Component
struct Index {
@State game: Game = new Game()
build() {
Stack() {
...
Row() {
Blank().layoutWeight(1).height('100%')
.gesture(
LongPressGesture({ repeat: true, duration: 5 })
.onAction((event: GestureEvent) => {
if (event && event.repeat) {
this.game.userShip?.moveRL(-1)
}
})
)
Blank().layoutWeight(1).height('100%')
.gesture(
LongPressGesture({ repeat: true, duration: 5 })
.onAction((event: GestureEvent) => {
if (event && event.repeat) {
this.game.userShip?.moveRL(1)
}
})
)
}
}
.onDigitalCrown((event: CrownEvent) => {
this.game.userShip?.moveRL(event.degree / 2)
})
}
}
Game Over
We do not have a way to restart the game yet. We will use a custom pop-up to show the final score and restart the game when it is closed.
Add GameOverPopup under the components directory.
@Component
export default struct WinLosePopup {
@Link showPopup: boolean;
@Require score: number;
build() {
Column() {
Text('GAME OVER')
.fontColor(Color.Red)
Text(`Score: ${this.score}`)
.fontColor(Color.Grey)
Blank().size({ height: 8 })
Button() {
SymbolGlyph($r('sys.symbol.arrow_clockwise'))
.fontColor([Color.White])
}
.size({
width: '100%',
height: 32
})
.onClick(() => {
this.showPopup = false
})
}
.width('70%')
.backgroundColor(Color.White)
.padding(16)
}
}
Modify Index and open a pop-up when he game ends.
Set parameters and pop-up builder.
@State @Watch('gameOver') game: Game = new Game()
@State pop: boolean = false;
gameOver() {
this.pop = this.game.lives === 0
}
@Builder
gameOverPopupBuilder() {
GameOverPopup({
showPopup: this.pop,
score: this.game.score
})
}
Bind it.
build() {
Stack() {
...
}
.bindPopup(this.pop, {
builder: this.gameOverPopupBuilder(),
autoCancel: false,
onStateChange: (e) => {
if (!e.isVisible) {
this.game.restart()
}
},
})
}
Let's add the restart function.
restart() {
this.canvasContext.clearRect(0, 0, this.canvasWidth, this.canvasHeight)
this.enemies = []
this.bullets = []
this.score = 0
this.lives = 3
this.userShip = new Ship(
this.canvasWidth, this.canvasHeight, this.PIXELSIZE,
ShipType.USER, this.FRAMECOUNT
)
this.intervalId = setInterval(() => {
this.iterateGame()
}, 1000 / this.FRAMECOUNT) // 32 times per second
}
Stars
The space is full of stars. Let's see them. We will use the Particle component.
struct Index {
...
build() {
Stack() {
Particle({
particles: [
{
emitter: {
particle: {
type: ParticleType.POINT,
config: {
radius: 1,
},
count: -1,
lifetime: 3000,
},
emitRate: 10,
shape: ParticleEmitterShape.CIRCLE,
position: [0, 0],
},
velocity: {
speed: [30, 60],
angle: [90, 90]
}
}
]
}).size({ width: '100%', height: '100%' })
...
}
}
}
Conclusion
We did it, folks. We have created the Space Shooter game. Time to play and enjoy.
See you all in new adventures. :)
~ Fortuna Favet Fortibus




Top comments (0)