New Doodad: Blue Bird
* The blue bird follows the same base AI as the red bird (it has a target altitude that it tries to maintain, and it will dive at the player) but the blue bird flies in a sine wave pattern around its target altitude. It also has a longer scan radius to search for the player than the red bird. * The sine wave pattern of the blue bird means you may fly under its radar depending how high it is on average. Cheat codes that replace the player character are refactored to make it easier to extend, and new cheats have been added: * super azulian: play as the Red Azulian. * hyper azulian: play as the White Azulian. * bluebird: play as the new Bird (blue).
|
@ -2,9 +2,17 @@ ALL: build
|
||||||
|
|
||||||
.PHONY: build
|
.PHONY: build
|
||||||
build:
|
build:
|
||||||
doodad convert -t "Bird (red)" left-1.png left-2.png right-1.png right-2.png \
|
doodad convert -t "Bird (red)" red/left-1.png red/left-2.png red/right-1.png \
|
||||||
dive-left.png dive-right.png bird-red.doodad
|
red/right-2.png red/dive-left.png red/dive-right.png \
|
||||||
|
bird-red.doodad
|
||||||
doodad install-script bird.js bird-red.doodad
|
doodad install-script bird.js bird-red.doodad
|
||||||
|
doodad edit-doodad --tag "color=red" bird-red.doodad
|
||||||
|
|
||||||
|
doodad convert -t "Bird (blue)" blue/left-1.png blue/left-2.png blue/right-1.png \
|
||||||
|
blue/right-2.png blue/dive-left.png blue/dive-right.png \
|
||||||
|
bird-blue.doodad
|
||||||
|
doodad install-script bird.js bird-blue.doodad
|
||||||
|
doodad edit-doodad --tag "color=blue" bird-blue.doodad
|
||||||
|
|
||||||
# Tag the category for these doodads
|
# Tag the category for these doodads
|
||||||
for i in *.doodad; do\
|
for i in *.doodad; do\
|
||||||
|
|
|
@ -1,8 +1,26 @@
|
||||||
// Bird
|
// Bird (red and blue)
|
||||||
|
|
||||||
|
/*
|
||||||
|
Base A.I. behaviors (red bird) are:
|
||||||
|
|
||||||
|
- Tries to maintain original altitude in level and flies left/right.
|
||||||
|
- Divebombs the player to attack, then climbs back to its original
|
||||||
|
altitude when it hits a floor/wall.
|
||||||
|
|
||||||
|
Blue bird:
|
||||||
|
|
||||||
|
- Flies in a sine wave pattern (its target altitude fluctuates
|
||||||
|
around the bird's original placement on the level).
|
||||||
|
- Longer aggro radius to dive.
|
||||||
|
*/
|
||||||
|
|
||||||
let speed = 4,
|
let speed = 4,
|
||||||
Vx = Vy = 0,
|
Vx = Vy = 0,
|
||||||
altitude = Self.Position().Y; // original height in the level
|
color = Self.GetTag("color"), // informs our A.I. behaviors
|
||||||
|
searchStep = 12 // pixels to step while searching for a player
|
||||||
|
searchLimit = color === "blue" ? 24 : 12, // multiples of searchStep for aggro radius
|
||||||
|
altitude = Self.Position().Y, // original height in level
|
||||||
|
targetAltitude = altitude; // bird's target height to maintain
|
||||||
|
|
||||||
let direction = "left",
|
let direction = "left",
|
||||||
lastDirection = "left";
|
lastDirection = "left";
|
||||||
|
@ -42,6 +60,11 @@ function main() {
|
||||||
lastSampled = Point(0, 0);
|
lastSampled = Point(0, 0);
|
||||||
|
|
||||||
setInterval(() => {
|
setInterval(() => {
|
||||||
|
// Run blue bird A.I. if we are blue: moves our target altitude along a sine wave.
|
||||||
|
if (color === "blue") {
|
||||||
|
AI_BlueBird();
|
||||||
|
}
|
||||||
|
|
||||||
// Sample how far we've moved to detect hitting a wall.
|
// Sample how far we've moved to detect hitting a wall.
|
||||||
if (sampleTick % sampleRate === 0) {
|
if (sampleTick % sampleRate === 0) {
|
||||||
let curP = Self.Position()
|
let curP = Self.Position()
|
||||||
|
@ -65,8 +88,8 @@ function main() {
|
||||||
// If we are not flying at our original altitude, correct for that.
|
// If we are not flying at our original altitude, correct for that.
|
||||||
let curV = Self.Position();
|
let curV = Self.Position();
|
||||||
Vy = 0.0;
|
Vy = 0.0;
|
||||||
if (curV.Y != altitude) {
|
if (curV.Y != targetAltitude) {
|
||||||
Vy = curV.Y < altitude ? 1 : -1;
|
Vy = curV.Y < targetAltitude ? 1 : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Scan for the player character and dive.
|
// Scan for the player character and dive.
|
||||||
|
@ -114,9 +137,9 @@ function AI_ScanForPlayer() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
let stepY = 12, // number of pixels to skip
|
let stepY = searchStep, // number of pixels to skip
|
||||||
stepX = stepY,
|
stepX = stepY,
|
||||||
limit = stepX * 20, // furthest we'll scan
|
limit = stepX * searchLimit, // furthest we'll scan
|
||||||
scanX = scanY = 0,
|
scanX = scanY = 0,
|
||||||
size = Self.Size(),
|
size = Self.Size(),
|
||||||
fromPoint = Self.Position();
|
fromPoint = Self.Position();
|
||||||
|
@ -147,6 +170,35 @@ function AI_ScanForPlayer() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Sine wave controls for the Blue bird.
|
||||||
|
var sineLimit = 32,
|
||||||
|
sineCounter = 0,
|
||||||
|
sineDirection = 1,
|
||||||
|
sineFrequency = 5, // every 500ms
|
||||||
|
sineStep = 16;
|
||||||
|
|
||||||
|
// A.I. Subroutine: sine wave pattern (Blue bird).
|
||||||
|
function AI_BlueBird() {
|
||||||
|
// The main loop runs on a 100ms interval, control how frequently
|
||||||
|
// to adjust the bird's target velocity.
|
||||||
|
if (sineCounter > 0 && (sineCounter % sineFrequency) > 1) {
|
||||||
|
sineCounter++;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
sineCounter++;
|
||||||
|
|
||||||
|
targetAltitude += sineStep*sineDirection;
|
||||||
|
|
||||||
|
// Cap the distance between our starting altitude and sine-wave target.
|
||||||
|
if (targetAltitude < altitude && altitude - targetAltitude >= sineLimit) {
|
||||||
|
targetAltitude = altitude - sineLimit;
|
||||||
|
sineDirection = 1
|
||||||
|
} else if (targetAltitude > altitude && targetAltitude - altitude >= sineLimit) {
|
||||||
|
targetAltitude = altitude + sineLimit;
|
||||||
|
sineDirection = -1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// If under control of the player character.
|
// If under control of the player character.
|
||||||
function player() {
|
function player() {
|
||||||
let playerSpeed = 12,
|
let playerSpeed = 12,
|
||||||
|
|
BIN
dev-assets/doodads/bird/blue/dive-left.png
Normal file
After Width: | Height: | Size: 11 KiB |
BIN
dev-assets/doodads/bird/blue/dive-right.png
Normal file
After Width: | Height: | Size: 11 KiB |
BIN
dev-assets/doodads/bird/blue/left-1.png
Normal file
After Width: | Height: | Size: 12 KiB |
BIN
dev-assets/doodads/bird/blue/left-2.png
Normal file
After Width: | Height: | Size: 11 KiB |
BIN
dev-assets/doodads/bird/blue/right-1.png
Normal file
After Width: | Height: | Size: 12 KiB |
BIN
dev-assets/doodads/bird/blue/right-2.png
Normal file
After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 959 B After Width: | Height: | Size: 959 B |
Before Width: | Height: | Size: 989 B After Width: | Height: | Size: 989 B |
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.0 KiB |
Before Width: | Height: | Size: 1022 B After Width: | Height: | Size: 1022 B |
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.0 KiB |