Skip to content

Commit

Permalink
Add "Press space to play" text when not activated
Browse files Browse the repository at this point in the history
  • Loading branch information
keguigong committed Dec 14, 2023
1 parent 97b472a commit f9d93e6
Show file tree
Hide file tree
Showing 10 changed files with 283 additions and 43 deletions.
9 changes: 7 additions & 2 deletions game/HPBar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export default class HPBar {
flashIterations = 0

opacity = 0
enterTimer = 0

constructor(canvas: HTMLCanvasElement, spritePos: Position, canvasWidth: number) {
this.canvas = canvas
Expand All @@ -26,7 +27,10 @@ export default class HPBar {

update(deltaTime: number, hp: number) {
let paint = true
if (this.opacity < 1) {

if (this.enterTimer < HPBar.config.ENTER_DELAY) {
this.enterTimer += deltaTime
} else if (this.opacity < 1) {
this.opacity = Math.min(this.opacity + HPBar.config.FADE_SPEED, 1)
}

Expand Down Expand Up @@ -119,7 +123,8 @@ export default class HPBar {
FLASH_ITERATIONS: 3, // 闪动的次数
MAX_HP: 3,
HP_UNIT: 1,
FADE_SPEED: 0.035 // 淡入淡出的速度
FADE_SPEED: 0.035, // 淡入淡出的速度,
ENTER_DELAY: 1000 // 显示延时
}

static dimensions = {
Expand Down
6 changes: 3 additions & 3 deletions game/Horizon.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,17 +36,17 @@ export default class Horizon {
}

private init() {
this.addCloud()
this.mountain = new Mountain(this.canvas, Runner.bdaySpriteDefinition.MOUNTAIN, this.dimensions.WIDTH)
this.horizonLine = new HorizonLine(this.canvas, this.spritePos.HORIZON)
this.nightMode = new NightMode(this.canvas, this.spritePos.MOON, this.dimensions.WIDTH)
this.mountain = new Mountain(this.canvas, Runner.bdaySpriteDefinition.MOUNTAIN, this.dimensions.WIDTH)
this.addCloud()
}

update(deltaTime: number, speed: number, hasObstacles?: boolean, showNightMode: boolean = false) {
this.mountain.update(deltaTime, speed)
this.horizonLine.update(deltaTime, speed)
this.nightMode.update(showNightMode)
this.updateCloud(deltaTime, speed)
this.mountain.update()
if (hasObstacles) {
this.updateObstacles(deltaTime, speed)
}
Expand Down
6 changes: 3 additions & 3 deletions game/Mountain.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,8 @@ export default class Mountain {
this.ctx.restore()
}

update() {
this.xPos = this.updateXPos(this.xPos, Mountain.config.MOUNTAIN_SPEED)
update(deltaTime: number, speed: number) {
this.xPos = this.updateXPos(this.xPos, Mountain.config.MOUNTAIN_SPEED * deltaTime)
this.draw()
}

Expand All @@ -73,6 +73,6 @@ export default class Mountain {
static config = {
WIDTH: 413,
HEIGHT: 92,
MOUNTAIN_SPEED: 0.1
MOUNTAIN_SPEED: 0.025
}
}
145 changes: 145 additions & 0 deletions game/PressToStart.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
import Runner from "./Runner"
import { IS_HIDPI } from "./varibles"

export default class PressToStart {
canvas!: HTMLCanvasElement
ctx!: CanvasRenderingContext2D
canvasDimensions!: Dimensions
textImgPos!: Position

animTimer = 0
opacity = 0
currTextIndex = 1
fadeIn = true

constructor(canvas: HTMLCanvasElement, textImgPos: Position, dimensions: Dimensions) {
this.canvas = canvas
this.ctx = canvas.getContext("2d")!
this.canvasDimensions = dimensions
this.textImgPos = textImgPos
}

drawText(dimensions: any) {
let centerX = this.canvasDimensions.WIDTH / 2

let textSourceX = dimensions.OFFSET_X
let textSourceY = dimensions.OFFSET_Y
let textSourceWidth = dimensions.TEXT_WIDTH
let textSourceHeight = dimensions.TEXT_HEIGHT

const textTargetX = Math.round(centerX - dimensions.TEXT_WIDTH / 2)
const textTargetY = Math.round((this.canvasDimensions.HEIGHT - 25) / 3)
const textTargetWidth = dimensions.TEXT_WIDTH
const textTargetHeight = dimensions.TEXT_HEIGHT

if (IS_HIDPI) {
textSourceX *= 2
textSourceY *= 2
textSourceWidth *= 2
textSourceHeight *= 2
}
textSourceX += this.textImgPos.x
textSourceY += this.textImgPos.y

this.ctx.save()
this.ctx.globalAlpha = this.opacity
this.ctx.drawImage(
Runner.imageSprite,
textSourceX,
textSourceY,
textSourceWidth,
textSourceHeight,
textTargetX,
textTargetY,
textTargetWidth,
textTargetHeight
)
this.ctx.restore()
this.ctx.globalAlpha = 1
}

drawEmoji(text: string, fadeOut = false) {
let centerX = this.canvasDimensions.WIDTH / 2
const textTargetY = 100
this.ctx.font = "16px system-ui, sans-serif"
this.ctx.textAlign = "center"
this.ctx.textBaseline = "middle"
this.ctx.save()
if (fadeOut) {
this.ctx.globalAlpha = this.opacity
}
this.ctx.fillStyle = "#6c6c6c"
this.ctx.fillText(text, centerX, textTargetY)
this.ctx.restore()
this.ctx.globalAlpha = 1
}

/**
* Update animation frames.
*/
update(deltaTime: number, fadeOut = false) {
if (this.opacity === 0 && fadeOut) return

if (this.opacity === 1) {
this.animTimer += deltaTime
if (this.animTimer > PressToStart.TEXT_PAUSE_DURATION) {
this.fadeIn = false
this.animTimer = 0
}
} else if (this.opacity === 0 && !this.fadeIn) {
this.fadeIn = true
this.currTextIndex = this.currTextIndex + 1 < PressToStart.TEXT_LIST.length ? this.currTextIndex + 1 : 0
}

if (fadeOut && this.opacity > 0) {
this.fadeIn = false
}

if (this.fadeIn) {
this.opacity = Math.min(1, this.opacity + PressToStart.FADE_SPEED * deltaTime)
} else {
this.opacity = Math.max(0, this.opacity - PressToStart.FADE_SPEED * deltaTime)
}

let textDimension = PressToStart.TEXT_LIST[this.currTextIndex]
this.drawText(textDimension)
this.drawEmoji("Code with 🖐️ & ❤️", fadeOut)
}

reset() {
this.animTimer = 0
}

static FADE_SPEED = 1 / 500
static TEXT_PAUSE_DURATION = 875
static TEXT_LIST = [
{
REMARK: "jp",
OFFSET_X: 0,
OFFSET_Y: 66,
TEXT_WIDTH: 222,
TEXT_HEIGHT: 14
},
{
REMARK: "zh",
OFFSET_X: 0,
OFFSET_Y: 80,
TEXT_WIDTH: 126,
TEXT_HEIGHT: 14
},
{
REMARK: "en",
OFFSET_X: 240,
OFFSET_Y: 66,
TEXT_WIDTH: 264,
TEXT_HEIGHT: 14
},
{
REMARK: "en",
OFFSET_X: 240,
OFFSET_Y: 80,
TEXT_WIDTH: 278,
TEXT_HEIGHT: 14
}
]
}
69 changes: 40 additions & 29 deletions game/Runner.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import DistanceMeter from "./DistanceMeter"
import GameOverPanel from "./GameOverPanel"
import PressToStart from "./PressToStart"
import HPBar from "./HPBar"
import Horizon from "./Horizon"
import Trex from "./Trex"
Expand All @@ -11,16 +12,15 @@ const RESOURCE_POSTFIX = "offline-resources-"
const BDAY_SPRITE_POSTFIX = "offline-bday-sprite-"

export default class Runner {
spriteDef!: SpritePosDef
canvas!: HTMLCanvasElement // Canvas object
ctx!: CanvasRenderingContext2D // Canvas context
spriteDef!: SpritePosDef // Sprite definition

outerContainerEl!: HTMLElement
containerEl!: HTMLElement

config: ConfigDict = Runner.config
dimensions = Runner.defaultDimensions

canvas!: HTMLCanvasElement
ctx!: CanvasRenderingContext2D
config: ConfigDict = Runner.config // Default configuration
dimensions = Runner.defaultDimensions // Canvas dimensions used for positioning and scaling

time = Date.now()
runningTime = 0
Expand All @@ -34,26 +34,27 @@ export default class Runner {
inverTimer = 0 // Night mode start time
invertTrigger = false
updatePending = false
resizeTimerId_: NodeJS.Timer | null = null
resizeTimerId_: NodeJS.Timer | null = null // window resizing delay

raqId = 0
raqId = 0 // requestAnimationFrame

tRex!: Trex // Paint objects
horizon!: Horizon
playingIntro!: boolean

msPerFrame = 1000 / FPS
distanceMeter!: DistanceMeter
gameOverPanel!: GameOverPanel
pressToStart!: PressToStart
hpBar!: HPBar

playingIntro!: boolean // Playing intro when first start

msPerFrame = 1000 / FPS // ms per frame
distanceRan = 0
highestScore = 0

tRex!: Trex
gameOverPanel!: GameOverPanel

audioContext!: AudioContext
soundFx: ConfigDict = {}
audioContext!: AudioContext // Collision sound
soundFx: ConfigDict = {} // Sound FX map

hpBar!: HPBar
hp = HPBar.config.MAX_HP
hp = HPBar.config.MAX_HP // HP value

constructor(outerContainerId: string, optConfig?: ConfigDict) {
this.outerContainerEl = document.querySelector(outerContainerId)!
Expand Down Expand Up @@ -130,14 +131,12 @@ export default class Runner {
Runner.updateCanvasScaling(this.canvas)
this.outerContainerEl.appendChild(this.containerEl)

// Load background clas s Horizon
// this.tRex = new Trex(this.canvas, this.spriteDef.TREX)
this.tRex = new Trex(this.canvas, Runner.bdaySpriteDefinition.TREX)
this.horizon = new Horizon(this.canvas, this.spriteDef, this.dimensions, this.config.GAP_COEFFICIENT)

this.distanceMeter = new DistanceMeter(this.canvas, this.spriteDef.TEXT_SPRITE, this.dimensions.WIDTH)

this.pressToStart = new PressToStart(this.canvas, this.spriteDef.TEXT_SPRITE, this.dimensions)
this.hpBar = new HPBar(this.canvas, Runner.bdaySpriteDefinition.HP, this.dimensions.WIDTH)
// this.tRex = new Trex(this.canvas, this.spriteDef.TREX)
this.tRex = new Trex(this.canvas, Runner.bdaySpriteDefinition.TREX)

this.startListening()
this.update()
Expand Down Expand Up @@ -258,7 +257,7 @@ export default class Runner {
}

this.collision = !!collision
hasObstacles && this.hpBar.update(deltaTime, this.hp)
this.hpBar.update(deltaTime, this.hp)

let playAchievementSound = this.distanceMeter.update(deltaTime, Math.ceil(this.distanceRan))

Expand Down Expand Up @@ -292,6 +291,17 @@ export default class Runner {
}
}

if (!this.activated) {
this.ctx.clearRect(0, 0, this.dimensions.WIDTH, this.dimensions.HEIGHT - 80)
this.tRex.update(deltaTime)
this.pressToStart.update(deltaTime)

this.scheduleNextUpdate()
return
} else {
this.pressToStart.update(deltaTime, true)
}

if (this.playing || (!this.activated && this.tRex.blinkCount < Runner.config.MAX_BLINK_COUNT)) {
this.tRex.update(deltaTime)

Expand Down Expand Up @@ -321,10 +331,11 @@ export default class Runner {
const messageEl = document.querySelector("#main-message") as HTMLDivElement
messageEl.style.opacity = "0"

let keyframes = `@-webkit-keyframes intro {
from { width: ${Trex.config.WIDTH}px }
to { width: ${this.dimensions.WIDTH}px } +
}`
// let keyframes = `@-webkit-keyframes intro {
// from { width: ${Trex.config.WIDTH}px }
// to { width: ${this.dimensions.WIDTH}px } +
// }`
let keyframes = `@-webkit-keyframes intro {}`
document.styleSheets[0].insertRule(keyframes, 0)
this.containerEl.style.webkitAnimation = "intro .4s ease-out 1 both"
this.containerEl.style.width = this.dimensions.WIDTH + "px"
Expand Down Expand Up @@ -714,7 +725,7 @@ export default class Runner {
GAMEOVER_CLEAR_TIME: 1200,
INITIAL_JUMP_VELOCITY: 12,
INVERT_FADE_DURATION: 12000,
MAX_BLINK_COUNT: 3,
MAX_BLINK_COUNT: Infinity,
MAX_CLOUDS: 6,
MAX_OBSTACLE_LENGTH: 3,
MAX_OBSTACLE_DUPLICATION: 2,
Expand Down
4 changes: 2 additions & 2 deletions game/Trex.ts
Original file line number Diff line number Diff line change
Expand Up @@ -282,7 +282,7 @@ export default class Trex {
]
}

static BLINK_TIMING = 7000
static BLINK_TIMING = 2000

static status = {
CRASHED: "CRASHED",
Expand All @@ -295,7 +295,7 @@ export default class Trex {
static animFrames: ConfigDict = {
WAITING: {
frames: [44, 0],
msPerFrame: 1000 / 3
msPerFrame: 1000 / 5
},
RUNNING: {
frames: [88, 132],
Expand Down
Loading

0 comments on commit f9d93e6

Please sign in to comment.