diff options
-rw-r--r-- | TODO | 12 | ||||
-rw-r--r-- | assets/tiles.png | bin | 5278 -> 5706 bytes | |||
-rw-r--r-- | level.go | 161 | ||||
-rwxr-xr-x | levelgen.py | 95 | ||||
-rw-r--r-- | main.go | 46 | ||||
-rw-r--r-- | objects.go | 12 |
6 files changed, 304 insertions, 22 deletions
@@ -1,10 +1,14 @@ # TODO + - [x] animatePlayer +- [ ] add particles +- [ ] subtle screen shake on death +- [ ] add an actual ending - [ ] animateExit -- [ ] add voiceover +- [x] add voiceover - [ ] add more levels -- [ ] add more items -- [ ] add enemies that you can control +- [x] add more items - [x] add << and || on pause and play -- [ ] add menu +- [x] add menu +- [ ] add hints (press e to edit again, r to reverse) diff --git a/assets/tiles.png b/assets/tiles.png Binary files differindex 846371e..682fa87 100644 --- a/assets/tiles.png +++ b/assets/tiles.png @@ -155,6 +155,7 @@ func StartLevel3(g *Game) { func StartLevel4(g *Game) { g.SetPlacing() + g.animStart = 0 noMoveable(g) g.toPlace = append(g.toPlace, NewSpring(g, 0, 0)) @@ -241,16 +242,166 @@ func StartLevel6(g *Game) { g.SetPlacing() //noMoveable(g) + g.ClearAll() + tilemap := NewTilemap([][]int{ + { +37, 38, 39, 37, 38, 39, 37, 38, 39, 37, 38, 39, 37, 38, 39, 37, 38, 39, 37, 38, 39, 37, 38, 39, 37, +53, 54, 55, 53, 54, 55, 53, 54, 55, 53, 54, 55, 53, 54, 55, 53, 54, 55, 53, 54, 55, 53, 54, 55, 53, +69, 70, 71, 69, 70, 71, 69, 70, 71, 69, 70, 71, 69, 70, 71, 69, 70, 71, 69, 70, 71, 69, 70, 71, 69, +37, 38, 39, 37, 38, 39, 37, 38, 39, 37, 38, 39, 37, 38, 39, 37, 38, 39, 37, 38, 39, 37, 38, 39, 37, +53, 54, 55, 53, 54, 55, 53, 54, 55, 53, 54, 55, 53, 54, 55, 53, 54, 55, 53, 54, 55, 53, 54, 55, 53, +69, 70, 71, 69, 70, 71, 69, 70, 71, 69, 70, 71, 69, 70, 71, 69, 70, 71, 69, 70, 71, 69, 70, 71, 69, +37, 38, 39, 37, 38, 39, 37, 38, 39, 37, 38, 39, 37, 38, 39, 37, 38, 39, 37, 38, 39, 37, 38, 39, 37, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 50, 34, 34, 34, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 34, 34, 34, 66, 0, +0, 70, 71, 69, 70, 71, 0, 0, 0, 0, 0, 50, 66, 0, 0, 0, 0, 0, 0, 70, 71, 69, 70, 71, 0, +0, 38, 39, 37, 38, 39, 0, 0, 0, 0, 0, 39, 37, 0, 0, 0, 0, 0, 0, 38, 39, 37, 38, 39, 0, +0, 54, 55, 53, 54, 55, 0, 0, 0, 0, 0, 55, 53, 0, 0, 0, 0, 0, 0, 54, 55, 53, 54, 55, 0, +0, 70, 71, 69, 70, 71, 0, 0, 0, 0, 0, 71, 69, 0, 0, 0, 0, 0, 0, 70, 71, 69, 70, 71, 0, +0, 38, 39, 37, 38, 39, 0, 0, 0, 0, 0, 39, 37, 0, 0, 0, 0, 0, 0, 38, 39, 37, 38, 39, 0, +0, 54, 55, 53, 54, 55, 0, 0, 0, 0, 0, 55, 53, 0, 0, 0, 0, 0, 0, 54, 55, 53, 54, 55, 0, +}, +{ +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 98, 82, 82, 82, 114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98, 82, 82, 82, 114, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98, 114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +}, + + }, 25) + + g.tilemap = &tilemap + g.tilemap.UpdateSurface() + g.player.startx = 22 * tileSize + g.player.starty = 8 * tileSize + + g.exit.startx = 2 * tileSize + g.exit.starty = 8 * tileSize + + g.ResetAll() + g.playerAi = g.playerAi[:0] + + g.QueueState(levelStart) + g.audioPlayer.voiceAudio[6].Play() - g.toPlace = append(g.toPlace, NewSpring(g, 0, 0)) - g.toPlace = append(g.toPlace, NewRightSideSpring(g, 0, 0)) - g.toPlace = append(g.toPlace, NewLeftSideSpring(g, 0, 0)) + g.toPlace = append(g.toPlace, NewHPlatform(g, 0, 0)) + g.toPlace = append(g.toPlace, NewHPlatform(g, 0, 0)) + + // after end + g.QueueState(ReverseLevel) + // after reversed + g.QueueState(afterReversed) + g.QueueState(StartLevel7) +} + +// How about this? +func StartLevel7(g *Game) { + g.SetPlacing() + //noMoveable(g) + + g.ClearAll() + tilemap := NewTilemap([][]int{ + { +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 50, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 66, 0, 0, 0, 0, 0, +0, 70, 71, 69, 70, 71, 69, 70, 71, 69, 70, 71, 69, 70, 71, 69, 70, 71, 69, 70, 0, 0, 0, 0, 0, +0, 38, 39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 54, 55, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 70, 71, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 38, 39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 54, 55, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 70, 71, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 38, 39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 54, 55, 34, 34, 34, 34, 34, 66, 0, 0, 0, 0, 0, 0, 0, 0, 50, 34, 34, 34, 34, 34, 66, 0, +0, 70, 71, 69, 70, 71, 69, 70, 71, 0, 0, 0, 0, 0, 0, 0, 50, 71, 69, 70, 71, 69, 70, 71, 0, +0, 38, 39, 37, 38, 39, 37, 38, 39, 0, 0, 0, 0, 0, 0, 0, 38, 39, 37, 38, 39, 37, 38, 39, 0, +0, 54, 55, 53, 54, 55, 53, 54, 55, 0, 0, 0, 0, 0, 0, 0, 54, 55, 53, 54, 55, 53, 54, 55, 0, +}, +{ +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 98, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 114, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 82, 82, 82, 82, 82, 114, 0, 0, 0, 0, 0, 0, 0, 0, 98, 82, 82, 82, 82, 82, 114, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +}, + + }, 25) + + g.tilemap = &tilemap + g.tilemap.UpdateSurface() + g.player.startx = 5 * tileSize + g.player.starty = 11 * tileSize + + g.exit.startx = 20 * tileSize + g.exit.starty = 11 * tileSize + + g.ResetAll() + g.playerAi = g.playerAi[:0] + + g.QueueState(levelStart) + + //g.audioPlayer.voiceAudio[3].Play() g.toPlace = append(g.toPlace, NewBox(g, 0, 0)) - g.exit.movable = true + g.toPlace = append(g.toPlace, NewBox(g, 0, 0)) + g.toPlace = append(g.toPlace, NewRightSideSpring(g, 0, 0)) + g.toPlace = append(g.toPlace, NewSpring(g, 0, 0)) // after end g.QueueState(ReverseLevel) // after reversed g.QueueState(afterReversed) - g.QueueState(StartLevel6) + g.QueueState(StartLevel8) +} + +func StartLevel8(g *Game) { + g.SetPlacing() + noMoveable(g) + g.toPlace = append(g.toPlace, NewVPlatform(g, 0, 0)) + g.toPlace = append(g.toPlace, NewBox(g, 0, 0)) + g.toPlace = append(g.toPlace, NewSpring(g, 0, 0)) + g.toPlace = append(g.toPlace, NewSpike(g, 0, 0)) + + g.exit.startx = 5 * tileSize + g.exit.starty = 1 * tileSize + g.exit.x = 5 * tileSize + g.exit.y = 1 * tileSize + + // after end + g.QueueState(ReverseLevel) + + // after reversed + g.QueueState(func (g *Game){ + afterReversed(g) + }) + g.QueueState(StartLevel7) } diff --git a/levelgen.py b/levelgen.py new file mode 100755 index 0000000..7e2e270 --- /dev/null +++ b/levelgen.py @@ -0,0 +1,95 @@ +#!/usr/bin/env python +array = [ + "#########################", + "#########################", + "#########################", + "#########################", + "#########################", + "#########################", + "#########################", + " ", + " ", + " ", + " ##### ##### ", + " ##### ## ##### ", + " ##### ## ##### ", + " ##### ## ##### ", + " ##### ## ##### ", + " ##### ## ##### ", + " ##### ## ##### ", + ] +#array = [ +# " ", +# " ", +# " ", +# " ", +# " ################### ", +# " ################### ", +# " ## ", +# " ## ", +# " ## ", +# " ## ", +# " ## ", +# " ## ", +# " ## ", +# " ######## ####### ", +# " ######## ######## ", +# " ######## ######## ", +# " ######## ######## ", +# ] + +def layer0(x, y, solid, topSurface, left, right): + + n = 0 + if solid and not topSurface: + n = 37 + n += x % 3 + n += (y % 3)*16 + + if topSurface and solid: + n = 34 + if left: + n += 16 + elif right: + n += 32 + + print ("%d, " % n, end="") + +def layer1(x, y, solid, topSurface, left, right): + + n = 0 + if topSurface and solid: + n = 82 + if left: + n += 16 + elif right: + n += 32 + + print ("%d, " % n, end="") + + +def calc(x, y): + + solid = array[y][x] == "#" + + topSurface = solid and (y != 0 and array[y-1][x] == " ") + left = x == 0 or array[y][x-1] == " " + right = (x+1) == len(array[0]) or array[y][x+1] == " " + return solid, topSurface, left, right + +print("{") +for y in range(len(array)): + for x in range(len(array[y])): + solid, topSurface, left, right = calc(x, y) + layer0(x, y, solid, topSurface, left, right) + + print("") +print("}, ") +print("{") +for y in range(len(array)): + for x in range(len(array[y])): + solid, topSurface, left, right = calc(x, y) + layer1(x, y, solid, topSurface, left, right) + + print("") +print("}, ") @@ -61,6 +61,8 @@ var ( cloudShader_src []byte //go:embed shaders/bloom.kage bloomShader_src []byte + //go:embed shaders/vortex.kage + vortexShader_src []byte //go:embed assets/tiles.png tilesPng_src []byte @@ -274,7 +276,7 @@ func (g *Game) Init() { g.surface = ebiten.NewImage(screenWidth, screenHeight) g.shaderName = "sky" g.state = MENU - + //StartGame(g)// TODO g.audioPlayer.ambientAudio.SetVolume(0) @@ -435,11 +437,6 @@ func (g *Game) UpdatePlacing() { } if inpututil.IsMouseButtonJustPressed(ebiten.MouseButton0) { - g.PlaceObject(cx, cy) - } -} - -func (g *Game) PlaceObject(cx, cy int) { if len(g.toPlace) == 0 { object := GetObjectAt(g.objects, float32(cx), float32(cy)) if object != nil { @@ -450,6 +447,16 @@ func (g *Game) PlaceObject(cx, cy int) { } return } + } else if inpututil.IsMouseButtonJustReleased(ebiten.MouseButton0) { + g.PlaceObject(cx, cy) + } +} + +func (g *Game) PlaceObject(cx, cy int) { + + if len(g.toPlace) == 0 { + return + } placeable := g.toPlace[0] if placeable.HasCollision(*g.tilemap, g.objects, NONE) { @@ -480,8 +487,26 @@ func DrawBackground(screen *ebiten.Image, time int) { screen.DrawRectShader(screenWidth, screenHeight, shaders["sky"], shop) } -func PostProcess(screen *ebiten.Image, shaderName string, time int) { +func PostProcess(screen *ebiten.Image, shaderName string, time int, game *Game) { w, h := screen.Bounds().Dx(), screen.Bounds().Dy() + + //out := ebiten.NewImage(w, h) + //shop := &ebiten.DrawRectShaderOptions{} + + //shop.Uniforms = map[string]any{ + // "Time": float32(time) / 60, + // "Ex": game.exit.x, + // "Ey": game.exit.y, + //} + //shop.Images[0] = screen + //shop.Images[1] = screen + //shop.Images[2] = screen + //shop.Images[3] = screen + //out.DrawRectShader(w, h, shaders["vortex"], shop) + + //op := &ebiten.DrawImageOptions{} + //screen.DrawImage(out, op) + for _, shader := range []string{shaderName} { out := ebiten.NewImage(w, h) shop := &ebiten.DrawRectShaderOptions{} @@ -669,7 +694,7 @@ func (g *Game) Draw(screen *ebiten.Image) { } - PostProcess(screen, g.shaderName, g.time) + PostProcess(screen, g.shaderName, g.time, g) //ebitenutil.DebugPrint(screen, fmt.Sprintf("tps: %.4f", ebiten.ActualFPS())) } @@ -702,6 +727,10 @@ func LoadShaders() error { if err != nil { return err } + shaders["vortex"], err = ebiten.NewShader([]byte(vortexShader_src)) + if err != nil { + return err + } return nil } func (g *Game) KillPlayer() { @@ -762,6 +791,7 @@ func (g *Game) SetPaused() { } func (g *Game) SetReversing() { g.state = REVERSING + g.audioPlayer.voiceAudio[0].Pause() rewindSpeed = 1 + int(len(g.recording) / 120) g.shaderName = "vcr" g.player.alpha = 1.0 @@ -11,7 +11,7 @@ import ( ) const ( - SPRING_FORCE = 8 + SPRING_FORCE = 7 SIDE_SPRING_FORCE = 8 ) @@ -57,7 +57,7 @@ type Player struct { func UpdateHPlatform(o * GameObject, tilemap Tilemap, others []*GameObject) bool { o.delta += 1 - if int(o.delta / 128) % 2 == 0 { + if int(o.delta / 160) % 2 == 0 { o.vx = -0.4 } else { o.vx = 0.4 @@ -69,7 +69,7 @@ func UpdateHPlatform(o * GameObject, tilemap Tilemap, others []*GameObject) bool func UpdateVPlatform(o * GameObject, tilemap Tilemap, others []*GameObject) bool { o.delta += 1 - if int(o.delta / 128) % 2 == 0 { + if int(o.delta / 160) % 2 == 0 { o.vy = -0.4 } else { o.vy = 0.4 @@ -162,7 +162,9 @@ func (o * GameObject) Update(tilemap Tilemap, others []*GameObject) { if ! o.onGround && o.vy > gravity*12 { o.PlayLand() } - o.onGround = true; + if direction == DOWN { + o.onGround = true; + } o.vx *= o.friction o.y -= o.vy @@ -378,7 +380,7 @@ func NewExit(game *Game, x, y float32) *GameObject{ exit := NewObject(game, x, y) exit.images = []*ebiten.Image{ - tilesImage.SubImage(image.Rect(0, 16, 32, 48)).(*ebiten.Image), + tilesImage.SubImage(image.Rect(0, 16, 31, 48)).(*ebiten.Image), } exit.onCollideUp = OnCollideExit exit.onCollideDown = OnCollideExit |