Twin-stick shooter
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

237 lines
4.7 KiB

package main
import (
"math"
"math/rand"
"time"
"github.com/hajimehoshi/ebiten/v2"
)
func newWinLevel(p *gamePlayer) *Level {
l := &Level{
w: 256,
h: 256,
tileSize: 32,
player: p,
}
startX, startY := 108, 108
grid := make([][][]*ebiten.Image, l.w)
for x := 0; x < l.w; x++ {
grid[x] = make([][]*ebiten.Image, l.h)
}
// Add ground.
var lastBones int
bonesDistance := 7
for x := 0; x < l.w; x++ {
excludeBones := x-lastBones < bonesDistance
r := rand.Intn(33)
switch r {
case 0:
grid[x][startY] = []*ebiten.Image{
ojasDungeonSS.Grass11,
}
case 1:
grid[x][startY] = []*ebiten.Image{
ojasDungeonSS.Grass12,
}
case 2:
grid[x][startY] = []*ebiten.Image{
ojasDungeonSS.Grass13,
}
case 3:
grid[x][startY] = []*ebiten.Image{
ojasDungeonSS.Grass14,
}
case 4:
grid[x][startY] = []*ebiten.Image{
ojasDungeonSS.Grass15,
}
case 5:
grid[x][startY] = []*ebiten.Image{
ojasDungeonSS.Grass16,
}
}
grid[x][startY+1] = []*ebiten.Image{
ojasDungeonSS.Grass21,
}
grid[x][startY+2] = []*ebiten.Image{
ojasDungeonSS.Grass31,
}
if rand.Intn(33) != 0 || excludeBones {
grid[x][startY+3] = []*ebiten.Image{
ojasDungeonSS.Grass41,
}
} else {
grid[x][startY+3] = []*ebiten.Image{
ojasDungeonSS.Grass42,
}
}
grid[x][startY+4] = []*ebiten.Image{
ojasDungeonSS.Grass51,
}
grid[x][startY+5] = []*ebiten.Image{
ojasDungeonSS.Grass61,
}
grid[x][startY+6] = []*ebiten.Image{
ojasDungeonSS.Grass71,
}
if rand.Intn(33) != 0 || excludeBones {
grid[x][startY+7] = []*ebiten.Image{
ojasDungeonSS.Grass81,
}
} else {
grid[x][startY+7] = []*ebiten.Image{
ojasDungeonSS.Grass82,
}
}
grid[x][startY+8] = []*ebiten.Image{
ojasDungeonSS.Grass91,
}
}
// Add dungeon.
for x := 0; x < 64; x++ {
for y := 0; y < 64; y++ {
grid[startX-x-1][startY-y] = []*ebiten.Image{
ojasDungeonSS.Wall1,
}
if y == 0 && x%8 == 0 {
grid[startX-x-1][startY-y] = append(grid[startX-x-1][startY-y], ojasDungeonSS.Vent1)
}
}
}
grid[startX-1][startY-1] = append(grid[startX-1][startY-1], ojasDungeonSS.Door11)
grid[startX-1][startY] = append(grid[startX-1][startY], ojasDungeonSS.Door12)
// Add sprites to tiles.
l.tiles = make([][]*Tile, l.h)
for y := 0; y < l.h; y++ {
l.tiles[y] = make([]*Tile, l.w)
for x := 0; x < l.w; x++ {
t := &Tile{}
for _, sprite := range grid[x][y] {
t.AddSprite(sprite)
}
l.tiles[y][x] = t
}
}
l.bakeLightmap()
doorX := float64(startX) - 0.4
p.angle = 0
p.x, p.y = doorX, float64(startY)
go func() {
// Walk away.
for i := 0; i < 36; i++ {
p.x += 0.05
time.Sleep(time.Second / 144)
}
for i := 0; i < 288; i++ {
p.x += 0.05 * (float64(288-i) / 288)
time.Sleep(time.Second / 144)
}
// Turn around.
p.angle = math.Pi
time.Sleep(time.Millisecond * 1750)
// Throw weapon.
weaponSprite := newCreep(TypeTorch, l, p)
weaponSprite.x, weaponSprite.y = p.x, p.y-0.25
weaponSprite.frames = 1
weaponSprite.frame = 0
weaponSprite.sprites = []*ebiten.Image{
imageAtlas[ImageUzi],
}
p.weapon = nil
l.creeps = append(l.creeps, weaponSprite)
go func() {
for i := 0; i < 144*2; i++ {
if weaponSprite.x < doorX {
for i, c := range l.creeps {
if c == weaponSprite {
l.creeps = append(l.creeps[:i], l.creeps[i+1:]...)
}
}
return
}
weaponSprite.x -= 0.05
if i < 100 {
weaponSprite.y -= 0.005 * (float64(144-i) / 144)
} else {
weaponSprite.y += 0.01 * (float64(288-i) / 288)
}
weaponSprite.angle -= .1
time.Sleep(time.Second / 144)
}
}()
time.Sleep(time.Second / 2)
// Throw torch.
torchSprite := newCreep(TypeTorch, l, p)
torchSprite.x, torchSprite.y = p.x, p.y-0.25
torchSprite.frames = 1
torchSprite.frame = 0
torchSprite.sprites = []*ebiten.Image{
sandstoneSS.TorchMulti,
}
p.hasTorch = false
l.creeps = append(l.creeps, torchSprite)
go func() {
for i := 0; i < 144*3; i++ {
if torchSprite.x < doorX {
for i, c := range l.creeps {
if c == torchSprite {
l.creeps = append(l.creeps[:i], l.creeps[i+1:]...)
}
}
}
torchSprite.x -= 0.05
if i < 100 {
torchSprite.y -= 0.005 * (float64(144-i) / 144)
} else {
torchSprite.y += 0.01 * (float64(288-i) / 288)
}
torchSprite.angle -= .1
time.Sleep(time.Second / 144)
}
}()
// Walk away.
time.Sleep(time.Second)
p.angle = 0
for i := 0; i < 144; i++ {
p.x += 0.05 * (float64(i) / 144)
time.Sleep(time.Second / 144)
}
for i := 0; i < 144*15; i++ {
if p.health > 0 {
// Game has restarted.
return
}
p.x += 0.05
time.Sleep(time.Second / 144)
}
}()
return l
}