Death Barrier and Player Character Cheat Codes

* Added the Death Barrier to Play Mode to catch players from falling off
  the map and then falling indefinitely, especially on Unbounded maps.
* The Death Barrier is set 1,000 pixels below the lowest point on your
  map. If the player falls here they get a death message: "Watch out for
  falling off the map!"
* Added cheat codes to change the default Player Character doodad, as a
  way to force play as a different character (for levels which don't
  specify a custom character):
  * Play as Bird: fly like a bird
  * Play as Blue Azulian: the cell
  * Play as Thief: play as thief
  * Reset to default (Boy): pinocchio
This commit is contained in:
Noah 2021-08-15 17:01:18 -07:00
parent 405aaf509d
commit 0bf5045a53
3 changed files with 123 additions and 5 deletions

View File

@ -1,5 +1,93 @@
# Changes
## v0.8.0 (TBD)
To Do:
* Thief needs animations
* New levels
This release brings some new features, new doodads, and new levels.
New features:
* **All Characters are Playable!** Use the Link Tool to connect your
Start Flag with another doodad on your level, and you will play
**as** that doodad when the level starts. The Creature doodads are
all intended to be fully functional; playing as buttons and doors
leads to strange results.
New doodads have been added:
* The **Anvil** is a heavy metal object which is affected by gravity.
It is harmless to collision, but if the anvil is in freefall, it
will destroy every mobile doodad that it touches, and is deadly
to the player character.
* The **Electric Trapdoor** is a trapdoor that opens and closes when
powered by a button or switch. It is a horizontal version of the
Electric Door.
* The **Thief** is a new character which will steal items from the
player or other mobile doodads. The Thief is able to pick up items
and unlock doors and he walks back and forth like the Azulians.
* The **Blue Azulian** is now selectable from the Doodads menu. It
behaves like the Red Azulian but moves at half the speed. The
Azulians can pick up items and open doors.
Some doodads have changed behavior:
* The **Bird** can no longer pick up items, unless controlled by
the player character.
* The **Anvil** and **Box** will reset to their original locations
if they receive a power signal from a linked button or switch.
The user interface has been improved:
* **Tabbed windows!** The Doodad Dropper window of the level editor
and the Settings window use new, tabbed interfaces.
* **Doodad Categories:** the Doodad Dropper's tabs are divided into
a few major categories.
1. Objects: Anvil, Box, Crumbly Floor, and Flags
2. Doors: Doors, Trapdoors, and Keys
3. Gizmos: Buttons, Switches, Electric Doors, etc.
4. Creatures: Bird, Azulians, Thief
5. All: a classic view paging over all doodads (and doodads
not fitting any of the above categories).
doodad edit-doodad --tag "categories=doors,gizmos" filename.doodad
New functions are available in the JavaScript API for custom doodads:
* FailLevel(message string): global function that kills the player
with a custom death message.
* Self.MoveTo(Point(x, y int))
* Self.IsPlayer() bool
* Self.SetInventory(bool): turn on or off inventory. Keys and other
items will now only give themselves to mobile doodads which have
inventory.
* Self.HasInventory() bool
* Self.AddItem(filename string, quantity int) - zero quantity for
permanent items like the colored keys.
* Self.RemoveItem(filename string, quantity int)
* Self.HasItem(filename string)
* Self.Inventory() map[string]int
The Events.OnLeave() callback now receives a CollideEvent argument,
like OnCollide, instead of the useless actor ID string. Notable
properties on the CollideEvent will be the .Actor which is leaving
and Settled=true.
Other miscellaneous changes:
* The **Link Tool** can now un-link two doodads by clicking on
them again.
* Actor UUIDs in your levels will now be Type 1 UUIDs (time-based)
instead of random. This will ensure each newly added doodad gets
a larger ID than the previous one, so in cases of draw order
conflicts or that sort of thing, the winner can be picked
deterministically (most recently added renders on top).
* A **death barrier** will prevent Boy from falling forever on unbounded
maps should he somehow fall off the level. The death barrier is a
Y value 1,000 pixels below the lowest pixel on your map.
## v0.7.2 (July 19 2021)
This release brings some new features and some new content.

View File

@ -1,5 +1,7 @@
package doodle
import "git.kirsle.net/apps/doodle/pkg/balance"
// cheatCommand is a subroutine of the Command.Run() method of the Doodle
// developer shell (commands.go). It looks for special cheat codes entered
// into the command shell and executes them.
@ -86,6 +88,22 @@ func (c Command) cheatCommand(d *Doodle) bool {
d.Flash("Use this cheat in Play Mode to clear your inventory.")
}
case "fly like a bird":
balance.PlayerCharacterDoodad = "bird-red.doodad"
d.Flash("Set default player character to Bird (red)")
case "pinocchio":
balance.PlayerCharacterDoodad = "boy.doodad"
d.Flash("Set default player character to Boy")
case "the cell":
balance.PlayerCharacterDoodad = "azu-blu.doodad"
d.Flash("Set default player character to Blue Azulian")
case "play as thief":
balance.PlayerCharacterDoodad = "thief.doodad"
d.Flash("Set default player character to Thief")
default:
return false
}

View File

@ -31,6 +31,7 @@ type PlayScene struct {
drawing *uix.Canvas
scripting *scripting.Supervisor
running bool
deathBarrier int // Y position of death barrier in case of falling OOB.
// UI widgets.
supervisor *ui.Supervisor
@ -211,6 +212,12 @@ func (s *PlayScene) setupAsync(d *Doodle) error {
s.drawing.InstallActors(s.Level.Actors)
}
// Choose a death barrier in case the user falls off the map,
// so they don't fall forever.
worldSize := s.Level.Chunker.WorldSize()
s.deathBarrier = worldSize.H + 1000
log.Debug("Death barrier at %d", s.deathBarrier)
// Set the loading screen text with the level metadata.
loadscreen.SetSubtitle(
s.Level.Title,
@ -257,7 +264,7 @@ func (s *PlayScene) setupPlayer() {
playerCharacterFilename = balance.PlayerCharacterDoodad
spawn render.Point
flag *level.Actor
flag = &level.Actor{}
flagSize = render.NewRect(86, 86) // TODO: start-flag.doodad is 86x86 px
flagCount int
)
@ -483,6 +490,11 @@ func (s *PlayScene) Loop(d *Doodle, ev *event.State) error {
log.Error("Drawing loop error: %s", err.Error())
}
// Check if the player hit the death barrier.
if s.Player.Position().Y > s.deathBarrier {
s.DieByFire("falling off the map")
}
// Update the inventory HUD.
s.computeInventory()
}