Add a Super-Speed Power-Up
We’re going to be implementing a new entity that when your player collides with it, it increases their speed for ten seconds when they collide with it.
Creating Art
You can use the Dreamlab asset creator to create art for your powerup. You can access it from the editor menu (openable with backtick `)
On this page, you can make a sketch and type a prompt to generate an image using AI. I made a pill with a lightning bolt but you can do whatever you want!
After you’ve created it, it will appear in your “Assets” tab in the Dreamlab sidebar.
Writing the Scripts
Create a New Entity
import type { SpawnableContext, Time } from '@dreamlab.gg/core'
import { game } from '@dreamlab.gg/core/labs'
import { z } from '@dreamlab.gg/core/sdk'
import { Solid, SolidArgs } from '@dreamlab.gg/core/entities'
export const SpeedBoostArgs = SolidArgs.extend({
amount: z.number().default(4),
duration: z.number().default(10),
})
export class SpeedBoost extends Solid<typeof SpeedBoostArgs> {
private lifeTime = 1000
public constructor(ctx: SpawnableContext<typeof SpeedBoostArgs>) {
super(ctx)
this.transform.zIndex = -10
if (this.body) {
this.body.isSensor = true
}
if (!this.tags.includes('net/replicated')) {
this.tags.push('net/replicated')
}
if (!this.tags.includes('editor/doNotSave'))
this.tags.push('editor/doNotSave')
// replace this with the URL you copied when creating your own art
this.args.spriteSource = {
url: 'https://s3-assets.dreamlab.gg/uploaded-from-editor/speed-pill-1717034434636.png',
}
}
public die(): void {
const $game = game('server')
if (!$game) return
$game.destroy(this)
return
}
public expire() {
this.lifeTime -= 1
if (this.lifeTime <= 0) {
this.die()
return
}
}
override onPhysicsStep(_: Time) {
this.expire()
}
}
Register Your Entity
import { SpeedBoost, SpeedBoostArgs } from './entities/SpeedBoost.ts'
// this gets run on both the client and the server
export const sharedInit: InitShared = game => {
// disable gravity since this game is top-down
game.physics.engine.gravity.scale = 0
// other entities being registered ...
// register our speedboost powerup entity
game.register('SpeedBoost', SpeedBoost, SpeedBoostArgs)
}
Add Ability For Player to Pick Up Speedboost
Inside the onCollide
function in the BulletHeavenPlayer
class, we can add the following snippet
onCollide([a, b]: readonly [SpawnableEntity, SpawnableEntity]) {
// ...
if (other instanceof SpeedBoost) {
// only run pick-up code on client.
const $game = game('client')
if (!$game) return
// destroy picked up SpeedBoost on server to make it disappear for other players
network('client')?.sendCustomMessage('DESTROY_BY_ID', { uid: other.uid })
// destroy on client
$game.destroy(other)
// add our speed buff
this.args.speed += other.args.amount
// if we have a timer running down, cancel it
if (this.speedBuffTimer) {
clearTimeout(this.speedBuffTimer)
}
// clear the speed buff after the specified duration.
this.speedBuffTimer = setTimeout(() => {
this.args.speed = this.baseSpeed;
}, other.args.duration * 1000)
}
}
You’ll also need to add a speedBuffTimer
property to the class to store the timer.
Making Enemies Drop Speed Buffs
In the die
function, we can give our enemies a 20% chance of dropping our new SpeedBoost item.
public die(): void {
// ...
if (Math.random() < 0.2) {
$game?.spawn({
entity: "SpeedBoost",
args: {
spriteSource: { url: "world://assets/symboo.png" },
amount: 4,
duration: 10
},
transform: { position: this.transform.position }
})
}
}