Prepare v0.11.0 for release (+ fixes)

* The title screen now loads the default maps from a LevelPack. The game
  no longer ships with the Tutorial levels in the "levels" folder as
  default; they are in the LevelPack so the "Edit Drawing" screen begins
  as a blank slate for only user levels.
* Add the Zoo level to the Tutorial levelpack
* Bugfixes around changing the player character to work around clipping
  issues if the character has changed height drastically.
This commit is contained in:
Noah 2022-02-20 17:46:16 -08:00
parent 293ac668e7
commit 40cb9f15cb
7 changed files with 72 additions and 40 deletions

View File

@ -1,6 +1,6 @@
# Changes # Changes
## v0.11.0 (TBD) ## v0.11.0 (Feb 20 2022)
New features: New features:
@ -23,6 +23,12 @@ New features:
more streamlined to just a checkbox for automatically bundling your more streamlined to just a checkbox for automatically bundling your
doodads next time you save the level. doodads next time you save the level.
New level:
* **The Zoo:** part of the Tutorial levelpack, it shows off all of the
game's built-in doodads and features a character selection room to
play as different creatures.
Some of the built-in doodads have updates to their A.I. and creatures Some of the built-in doodads have updates to their A.I. and creatures
are becoming more dangerous: are becoming more dangerous:

View File

@ -147,33 +147,3 @@ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
``` ```
### github.com/vmihailenco/msgpack
```
Copyright (c) 2013 The github.com/vmihailenco/msgpack Authors.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
```

View File

@ -119,8 +119,6 @@ def copy_assets():
"""Copy assets from other repos into doodle.""" """Copy assets from other repos into doodle."""
if not os.path.isdir("assets/fonts"): if not os.path.isdir("assets/fonts"):
shell("cp -rv deps/vendor/fonts assets/fonts") shell("cp -rv deps/vendor/fonts assets/fonts")
if not os.path.isdir("assets/levels"):
shell("cp -rv deps/masters/levels assets/levels")
if not os.path.isdir("assets/levelpacks"): if not os.path.isdir("assets/levelpacks"):
shell("cp -rv deps/masters/levelpacks/levelpacks assets/levelpacks") shell("cp -rv deps/masters/levelpacks/levelpacks assets/levelpacks")
if not os.path.isdir("rtp"): if not os.path.isdir("rtp"):

View File

@ -65,7 +65,8 @@ var (
// Default player character doodad in Play Mode. // Default player character doodad in Play Mode.
PlayerCharacterDoodad = "boy.doodad" PlayerCharacterDoodad = "boy.doodad"
// Level names for the title screen. // Levelpack and level names for the title screen.
DemoLevelPack = "assets/levelpacks/001000-TUTORIAL.levelpack"
DemoLevelName = []string{ DemoLevelName = []string{
"Tutorial 1.level", "Tutorial 1.level",
"Tutorial 2.level", "Tutorial 2.level",

View File

@ -9,7 +9,7 @@ import (
const ( const (
AppName = "Sketchy Maze" AppName = "Sketchy Maze"
Summary = "A drawing-based maze game" Summary = "A drawing-based maze game"
Version = "0.10.2" Version = "0.11.0"
Website = "https://www.sketchymaze.com" Website = "https://www.sketchymaze.com"
Copyright = "2022 Noah Petherbridge" Copyright = "2022 Noah Petherbridge"
Byline = "a game by Noah Petherbridge." Byline = "a game by Noah Petherbridge."

View File

@ -301,15 +301,57 @@ func (s *MainScene) SetupDemoLevel(d *Doodle) error {
s.canvas.SetScriptSupervisor(s.scripting) s.canvas.SetScriptSupervisor(s.scripting)
// Title screen level to load. Pick a random level. // Title screen level to load. Pick a random level.
levelName := balance.DemoLevelName[0] var (
levelName = balance.DemoLevelName[0]
fromLevelPack = true
lvl *level.Level
)
if s.LevelFilename != "" { if s.LevelFilename != "" {
// User provided a custom level name, nix the demo levelpack.
levelName = s.LevelFilename levelName = s.LevelFilename
fromLevelPack = false
} else if len(balance.DemoLevelName) > 1 { } else if len(balance.DemoLevelName) > 1 {
randIndex := rand.Intn(len(balance.DemoLevelName)) randIndex := rand.Intn(len(balance.DemoLevelName))
levelName = balance.DemoLevelName[randIndex] levelName = balance.DemoLevelName[randIndex]
} }
if lvl, err := level.LoadFile(levelName); err == nil { // Get the level from the DemoLevelPack?
if fromLevelPack {
log.Debug("Initializing titlescreen from DemoLevelPack: %s", balance.DemoLevelPack)
lp, err := levelpack.LoadFile(balance.DemoLevelPack)
if err != nil {
log.Error("Error loading DemoLevelPack(%s): %s", balance.DemoLevelPack, err)
} else {
log.Debug("Loading selected level from pack: %s", levelName)
levelbin, err := lp.GetData("levels/" + levelName)
if err != nil {
log.Error("Error getting level from DemoLevelpack(%s#%s): %s",
balance.DemoLevelPack,
levelName,
err,
)
} else {
log.Debug("Parsing loaded level data (%d bytes)", len(levelbin))
lvl, err = level.FromJSON(levelName, levelbin)
if err != nil {
log.Error("DemoLevelPack FromJSON(%s): %s", levelName, err)
lvl = nil
}
}
}
}
// May be a user-provided level.
if lvl == nil {
if trylvl, err := level.LoadFile(levelName); err == nil {
lvl = trylvl
} else {
log.Error("Error loading demo level %s: %s", balance.DemoLevelName, err)
}
}
// If still no level, initialize a basic notebook background.
if lvl != nil {
s.canvas.LoadLevel(lvl) s.canvas.LoadLevel(lvl)
s.canvas.InstallActors(lvl.Actors) s.canvas.InstallActors(lvl.Actors)
@ -323,8 +365,6 @@ func (s *MainScene) SetupDemoLevel(d *Doodle) error {
log.Error("Error running actor main() functions: %s", err) log.Error("Error running actor main() functions: %s", err)
} }
} else { } else {
log.Error("Error loading demo level %s: %s", balance.DemoLevelName, err)
// Create a basic notebook level. // Create a basic notebook level.
s.canvas.LoadLevel(&level.Level{ s.canvas.LoadLevel(&level.Level{
Chunker: level.NewChunker(100), Chunker: level.NewChunker(100),

View File

@ -296,7 +296,16 @@ func (s *PlayScene) setupAsync(d *Doodle) error {
// SetPlayerCharacter changes the doodad used for the player, by destroying the // SetPlayerCharacter changes the doodad used for the player, by destroying the
// current player character and making it from scratch. // current player character and making it from scratch.
func (s *PlayScene) SetPlayerCharacter(filename string) { func (s *PlayScene) SetPlayerCharacter(filename string) {
spawn := s.Player.Position() // Record the player position and size and back up their inventory.
var (
spawn = s.Player.Position()
inventory = s.Player.Inventory()
)
// TODO: to account for different height players, the position ought to be
// adjusted so the player doesn't clip and fall thru the floor.
spawn.Y -= 20 // work-around
s.Player.Destroy() s.Player.Destroy()
s.drawing.RemoveActor(s.Player) s.drawing.RemoveActor(s.Player)
@ -305,6 +314,11 @@ func (s *PlayScene) SetPlayerCharacter(filename string) {
if err := s.drawing.InstallScripts(); err != nil { if err := s.drawing.InstallScripts(); err != nil {
log.Error("SetPlayerCharacter: InstallScripts: %s", err) log.Error("SetPlayerCharacter: InstallScripts: %s", err)
} }
// Restore their inventory.
for item, qty := range inventory {
s.Player.AddItem(item, qty)
}
} }
// setupPlayer creates and configures the Player Character in the level. // setupPlayer creates and configures the Player Character in the level.
@ -646,6 +660,9 @@ func (s *PlayScene) Loop(d *Doodle, ev *event.State) error {
// Check if the player hit the death barrier. // Check if the player hit the death barrier.
if s.Player.Position().Y > s.deathBarrier { if s.Player.Position().Y > s.deathBarrier {
// The player must die to avoid the softlock of falling forever.
s.godMode = false
s.Player.SetInvulnerable(false)
s.DieByFire("falling off the map") s.DieByFire("falling off the map")
} }