Skip to content

Commit

Permalink
Merge pull request #6 from Kikketer/boat-battle
Browse files Browse the repository at this point in the history
boat-battle
  • Loading branch information
Kikketer authored Jul 16, 2024
2 parents b6f5dd9 + 8fa9f5b commit 8ed7c2d
Show file tree
Hide file tree
Showing 14 changed files with 327 additions and 204 deletions.
103 changes: 100 additions & 3 deletions boatBattle.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,112 @@
namespace BoatBattle {
let enemies: Sprite[]
let enemies: EnemyPirate[] = []
let player1: Pirate
let player2: Pirate

const player1StatLocation: number[] = [12, 10]
const player2StatLocation: number[] = [130, 10]
let _onWinCallback: () => void
let _onAllDeadCallback: () => void

const _timeAllowed = 10
let _currentTime = _timeAllowed
let _lastTick = 0
let _isDone = false
const _boundingBox: number[] = [0, 10, 160, 120]
const _enemyBoatBox: number[] = [0, 10, 160, 60]

export function init() {
scene.setBackgroundColor(6)
scene.setBackgroundImage(assets.image`empty`)

_currentTime = _timeAllowed
_lastTick = control.millis()

// Spawn the players
// player1 = new Pirate({ control: controller.player1 })
player1 = new Pirate({ control: controller.player1, playerNumber: 0, onAttack: onPirateAttack, onDie: onPirateDeath, topBoundary: _boundingBox[1], statLocation: player1StatLocation })
player2 = new Pirate({ control: controller.player2, playerNumber: 1, onAttack: onPirateAttack, onDie: onPirateDeath, topBoundary: _boundingBox[1], statLocation: player2StatLocation })

// Spawn the enemies!
// Based on the amount of treasure you have, more enemies will appear!
const totalTreasure = TreasureStats.getTotal()
let numberOfEnemies = 1
if (totalTreasure > 1000) {
numberOfEnemies = 10
} else {
// A log curve to determine the number of enemies
numberOfEnemies = 4 + Math.log(TreasureStats.getTotal() + 1) / Math.log(1000) * 8;
}

Utils.getArrayOfLength(numberOfEnemies).forEach(() => {
const locX = Math.randomRange(_enemyBoatBox[0], _enemyBoatBox[2])
const locY = Math.randomRange(_enemyBoatBox[1], _enemyBoatBox[3])
const militia = new Militia({ x: locX, y: locY, target: Math.pickRandom([player1, player2]) })
enemies.push(militia)
})
}

export function render() {
player1.render()
player2.render()

enemies.forEach(enemy => enemy.render())

// Show timer (I know there's an extension but I want to try and roll my own)
if (control.millis() - _lastTick > 1000 && !_isDone) {
_lastTick = control.millis()
_currentTime -= 1
console.log('Time! ' + _currentTime)
}

if (_currentTime <= 0 && !_isDone && enemies.some((enemy) => enemy.health > 0)) {
_isDone = true
console.log('Game over!')
pause(1000)

destory()
_onAllDeadCallback()
}
}

export function destory() {
player1.destroy()
player2.destroy()
enemies.forEach((e) => e.destroy())

scene.setBackgroundImage(assets.image`empty`)
}

export function onWin(callback: () => void) {
_onWinCallback = callback
}

export function onAllDead(callback: () => void) {
_onAllDeadCallback = callback
}

export function destory() {}
function onPirateAttack({ pirate }: { pirate: Pirate }) {
const hitEnemies = Utils.getHitEnemies({ pirate, enemies })
hitEnemies.forEach((enemy) => {
// No looting of EnemyPirates
if (enemy.health > 0) {
enemy.hit(1)
}
})

checkIfWin()
}

function onPirateDeath() {}

function checkIfWin() {
const anyAlive = enemies.some((enemy) => enemy.health > 0)
if (!anyAlive) {
_isDone = true
console.log("you dit it!")
pause(1000)

destory()
_onWinCallback()
}
}
}
89 changes: 89 additions & 0 deletions enemy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
class Enemy {
static speed = 10

public sprite: Sprite
public health: number = 1
public riches = 1

protected _currentTarget: Pirate
protected _nextAttackTime: number = 0
protected _lastAttackTick: number = 0
protected _facing: 'left' | 'right' = 'left'
protected _isAttacking: boolean = false
protected _lastDirectionTick: number = 0

constructor({ x, y, target, sprite, riches }: { x: number, y: number, target: Pirate, sprite: Sprite, riches?: number }) {
this.sprite = sprite
this.sprite.x = x
this.sprite.y = y

this.riches = riches != null ? riches : 1

// On initial spawn they are quick to attack!
this._nextAttackTime = Math.randomRange(Militia.attackDelayMin / 2, Militia.attackDelayMax / 2)
this._lastAttackTick = control.millis()

this._currentTarget = target
}

public destroy() {
if (this.sprite) {
this.sprite.destroy()
}
}

public setCurrentTarget(pirate: Pirate) {
if (pirate.health > 0 && this.health > 0) {
this._currentTarget = pirate
this.sprite.follow(this._currentTarget.sprite, Enemy.speed)
}
}

protected walk(direction?: 'left' | 'right') {
this._facing = direction ? direction : this._facing
this.sprite.follow(this._currentTarget.sprite, Enemy.speed)
}

protected hit(damage: number) {
this.health -= damage

if (this.health <= 0) {
this.sprite.follow(this._currentTarget.sprite, 0)
}
}

protected attack() {
// Stop moving
console.log("Should stop!")
this.sprite.follow(this._currentTarget.sprite, 0)
this._isAttacking = true
}

protected die() {}

public render() {
// No Undead walking!
if (this.health <= 0 && !this._isAttacking) return

// Check your distance from the target randomly
if ((control.millis() - this._lastDirectionTick) > Militia.directionChangeInterval) {
this._lastDirectionTick = control.millis()
if (Math.abs(Utils.getDistance(
{ x: this.sprite.x, y: this.sprite.y },
{ x: this._currentTarget.sprite.x, y: this._currentTarget.sprite.y }
)) < 30) {
this.sprite.follow(this._currentTarget.sprite, 0)
} else {
this.sprite.follow(this._currentTarget.sprite, Enemy.speed)
}
}

// Face your target
if (this._currentTarget.sprite.x < this.sprite.x && this._facing === 'right' && !this._isAttacking) {
this.walk('left')
} else if (this._currentTarget.sprite.x > this.sprite.x && this._facing === 'left' && !this._isAttacking) {
this.walk('right')
}
this.sprite.z = this.sprite.y
}
}
7 changes: 7 additions & 0 deletions enemyPirate.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
class EnemyPirate extends Militia {
static walkRightAnimation: Image[] = assets.animation`Pirate Walk`

constructor({ x, y, target }: { x: number, y: number, target: Pirate }) {
super({ x, y, target })
}
}
10 changes: 5 additions & 5 deletions images.g.jres
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,6 @@
"mimeType": "image/x-mkcd-f4",
"displayName": "Boat Icon"
},
"image11": {
"data": "hwQIAAgAAAAAAAAA4ADu7u7d7e7u3e3u7t3u7uDd7u7gAO4OAAAAAA==",
"mimeType": "image/x-mkcd-f4",
"displayName": "Pocket Icon"
},
"image14": {
"data": "hwQIAAgAAAAAVUUAUFVVBFBVVQRQVVUEUFVVBFBVVQRQVVUEAFVFAA==",
"mimeType": "image/x-mkcd-f4",
Expand Down Expand Up @@ -84,6 +79,11 @@
"mimeType": "image/x-mkcd-f4",
"displayName": "Militia Broken and Broke Left"
},
"image11": {
"data": "hwQIAAgAAAAAAAAAAFAFAABRVQAQVVUEUFVVBABVRQAAQAQAAAAAAA==",
"mimeType": "image/x-mkcd-f4",
"displayName": "Pocket Icon"
},
"anim14": {
"namespace": "myAnimations",
"id": "anim14",
Expand Down
22 changes: 11 additions & 11 deletions images.g.ts
Original file line number Diff line number Diff line change
Expand Up @@ -296,17 +296,6 @@ e e e e e e e e
. e e e e e e e
. . e e e e e e
. . . . . . . .
`;
case "image11":
case "Pocket Icon":return img`
. . e e e . . .
. e e e e e e .
. . d d d d . .
. . d d d d . .
. e d d e e e .
. e e e e e e .
. e e e e e e .
. e e e e e . .
`;
case "image14":
case "Coin":return img`
Expand Down Expand Up @@ -514,6 +503,17 @@ d d a a a c c d d . . . . . . .
. . . f e e a a d d d d a . . f
. . . f e e c c a a a a c d d f
. . . f e e c a a a a a a d d f
`;
case "image11":
case "Pocket Icon":return img`
. . . . . . . .
. . . 1 5 . . .
. . 1 5 5 5 . .
. 5 5 5 5 5 4 .
. 5 5 5 5 5 4 .
. . 5 5 5 4 . .
. . . 4 4 . . .
. . . . . . . .
`;
}
return null;
Expand Down
Loading

0 comments on commit 8ed7c2d

Please sign in to comment.