Add levitate ability
parent
24660de4e8
commit
2485cf9a20
|
@ -17,6 +17,10 @@ var ImgBackground2 = LoadImage("image/szadiart-caves/background2.png")
|
|||
var ImgBackground3 = LoadImage("image/szadiart-caves/background3.png")
|
||||
var ImgBackground4 = LoadImage("image/szadiart-caves/background4a.png")
|
||||
|
||||
var ImgUzi = LoadImage("image/weapons/uzi.png")
|
||||
|
||||
var ImgBullet = LoadImage("image/weapons/bullet.png")
|
||||
|
||||
func LoadImage(p string) *ebiten.Image {
|
||||
f, err := FS.Open(p)
|
||||
if err != nil {
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 4.7 KiB |
Binary file not shown.
After Width: | Height: | Size: 1.3 KiB |
Binary file not shown.
After Width: | Height: | Size: 5.7 KiB |
2559
asset/map/m1.tmx
2559
asset/map/m1.tmx
File diff suppressed because it is too large
Load Diff
|
@ -15,10 +15,6 @@ type PlayerSpriteSheet struct {
|
|||
DuckR *ebiten.Image
|
||||
WalkR1 *ebiten.Image
|
||||
WalkR2 *ebiten.Image
|
||||
IdleL *ebiten.Image
|
||||
DuckL *ebiten.Image
|
||||
WalkL1 *ebiten.Image
|
||||
WalkL2 *ebiten.Image
|
||||
}
|
||||
|
||||
// LoadPlayerSpriteSheet loads the embedded PlayerSpriteSheet.
|
||||
|
@ -47,10 +43,6 @@ func LoadPlayerSpriteSheet() *PlayerSpriteSheet {
|
|||
s.WalkR1 = spriteAt(1, 0)
|
||||
s.WalkR2 = spriteAt(2, 0)
|
||||
s.DuckR = spriteAt(3, 0)
|
||||
s.IdleL = spriteAt(0, 1)
|
||||
s.WalkL1 = spriteAt(1, 1)
|
||||
s.WalkL2 = spriteAt(2, 1)
|
||||
s.DuckL = spriteAt(3, 1)
|
||||
|
||||
return s
|
||||
}
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
package component
|
||||
|
||||
import (
|
||||
"code.rocketnine.space/tslocum/gohan"
|
||||
"code.rocketnine.space/tslocum/monovania/engine"
|
||||
)
|
||||
|
||||
type DestructibleComponent struct {
|
||||
}
|
||||
|
||||
var DestructibleComponentID = engine.Engine.NewComponentID()
|
||||
|
||||
func (p *DestructibleComponent) ComponentID() gohan.ComponentID {
|
||||
return DestructibleComponentID
|
||||
}
|
||||
|
||||
func Destructible(ctx *gohan.Context) *DestructibleComponent {
|
||||
c, ok := ctx.Component(DestructibleComponentID).(*DestructibleComponent)
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
return c
|
||||
}
|
|
@ -15,6 +15,9 @@ type SpriteComponent struct {
|
|||
VerticalFlip bool
|
||||
DiagonalFlip bool // TODO unimplemented
|
||||
|
||||
Overlay *ebiten.Image
|
||||
OverlayX, OverlayY float64 // Overlay offset
|
||||
|
||||
Frame int
|
||||
Frames []*ebiten.Image
|
||||
FrameTime time.Duration
|
||||
|
|
|
@ -8,7 +8,7 @@ import (
|
|||
)
|
||||
|
||||
type WeaponComponent struct {
|
||||
Ammo int
|
||||
Equipped bool
|
||||
|
||||
Damage int
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@ func NewBullet(x, y, xSpeed, ySpeed float64) gohan.Entity {
|
|||
})
|
||||
|
||||
engine.Engine.AddComponent(bullet, &component.SpriteComponent{
|
||||
Image: asset.ImgWhiteSquare,
|
||||
Image: asset.ImgBullet,
|
||||
})
|
||||
|
||||
engine.Engine.AddComponent(bullet, &component.BulletComponent{})
|
||||
|
|
|
@ -20,7 +20,6 @@ func NewPlayer(x, y float64) gohan.Entity {
|
|||
engine.Engine.AddComponent(player, &component.VelocityComponent{})
|
||||
|
||||
weapon := &component.WeaponComponent{
|
||||
Ammo: 1000,
|
||||
Damage: 1,
|
||||
FireRate: 100 * time.Millisecond,
|
||||
BulletSpeed: 15,
|
||||
|
|
1
flags.go
1
flags.go
|
@ -52,5 +52,6 @@ func parseFlags() {
|
|||
|
||||
if noSplash {
|
||||
world.World.GameStarted = true
|
||||
world.World.MessageVisible = false
|
||||
}
|
||||
}
|
||||
|
|
17
game/game.go
17
game/game.go
|
@ -7,18 +7,13 @@ import (
|
|||
"os"
|
||||
"sync"
|
||||
|
||||
"code.rocketnine.space/tslocum/monovania/engine"
|
||||
|
||||
"code.rocketnine.space/tslocum/monovania/world"
|
||||
|
||||
"code.rocketnine.space/tslocum/monovania/component"
|
||||
|
||||
"code.rocketnine.space/tslocum/monovania/entity"
|
||||
|
||||
"code.rocketnine.space/tslocum/monovania/asset"
|
||||
|
||||
"code.rocketnine.space/tslocum/gohan"
|
||||
"code.rocketnine.space/tslocum/monovania/asset"
|
||||
"code.rocketnine.space/tslocum/monovania/component"
|
||||
"code.rocketnine.space/tslocum/monovania/engine"
|
||||
"code.rocketnine.space/tslocum/monovania/entity"
|
||||
"code.rocketnine.space/tslocum/monovania/system"
|
||||
"code.rocketnine.space/tslocum/monovania/world"
|
||||
"github.com/hajimehoshi/ebiten/v2"
|
||||
"github.com/hajimehoshi/ebiten/v2/audio"
|
||||
"golang.org/x/text/language"
|
||||
|
@ -101,6 +96,8 @@ func NewGame() (*game, error) {
|
|||
|
||||
asset.ImgWhiteSquare.Fill(color.White)
|
||||
|
||||
world.World.SetMessage("<J> TO JUMP.\n<R> TO REWIND.\n<WASD> TO MOVE.")
|
||||
|
||||
return g, nil
|
||||
}
|
||||
|
||||
|
|
4
go.mod
4
go.mod
|
@ -15,8 +15,8 @@ require (
|
|||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20211213063430-748e38ca8aec // indirect
|
||||
github.com/hajimehoshi/oto/v2 v2.1.0-alpha.4 // indirect
|
||||
github.com/jezek/xgb v0.0.0-20210312150743-0e0f116e1240 // indirect
|
||||
golang.org/x/exp v0.0.0-20211213173848-79cd87713b62 // indirect
|
||||
golang.org/x/exp v0.0.0-20211214223157-bafe2e20209a // indirect
|
||||
golang.org/x/mobile v0.0.0-20211207041440-4e6c2922fdee // indirect
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect
|
||||
golang.org/x/sys v0.0.0-20211214150614-024a26f5d6e2 // indirect
|
||||
golang.org/x/sys v0.0.0-20211214234402-4825e8c3871d // indirect
|
||||
)
|
||||
|
|
8
go.sum
8
go.sum
|
@ -38,8 +38,8 @@ golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8U
|
|||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190731235908-ec7cb31e5a56/go.mod h1:JhuoJpWY28nO4Vef9tZUw9qufEGTyX1+7lmHxV5q5G4=
|
||||
golang.org/x/exp v0.0.0-20211213173848-79cd87713b62 h1:NLQyV2V75F1Y0l2EyOgXGh0Z44+AlPxVIN6BHOniazA=
|
||||
golang.org/x/exp v0.0.0-20211213173848-79cd87713b62/go.mod h1:b9TAUYHmRtqA6klRHApnXMnj+OyLce4yF5cZCUbk2ps=
|
||||
golang.org/x/exp v0.0.0-20211214223157-bafe2e20209a h1:AAl9OocndjmqsjP37NRIXRsHZooES2MX3Imla+GKe5o=
|
||||
golang.org/x/exp v0.0.0-20211214223157-bafe2e20209a/go.mod h1:b9TAUYHmRtqA6klRHApnXMnj+OyLce4yF5cZCUbk2ps=
|
||||
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
||||
golang.org/x/image v0.0.0-20190703141733-d6a02ce849c9/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||
|
@ -72,8 +72,8 @@ golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210917161153-d61c044b1678/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211214150614-024a26f5d6e2 h1:oJg+vmWs1UY4oSg6n1drFSkU2Nc48mxtz5qhA0HaG0I=
|
||||
golang.org/x/sys v0.0.0-20211214150614-024a26f5d6e2/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211214234402-4825e8c3871d h1:1oIt9o40TWWI9FUaveVpUvBe13FNqBNVXy3ue2fcfkw=
|
||||
golang.org/x/sys v0.0.0-20211214234402-4825e8c3871d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
|
|
|
@ -27,6 +27,7 @@ func NewFireWeaponSystem(player gohan.Entity) *fireWeaponSystem {
|
|||
func (_ *fireWeaponSystem) Needs() []gohan.ComponentID {
|
||||
return []gohan.ComponentID{
|
||||
component.PositionComponentID,
|
||||
component.SpriteComponentID,
|
||||
component.WeaponComponentID,
|
||||
}
|
||||
}
|
||||
|
@ -35,55 +36,39 @@ func (_ *fireWeaponSystem) Uses() []gohan.ComponentID {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (s *fireWeaponSystem) fire(weapon *component.WeaponComponent, position *component.PositionComponent, fireAngle float64) {
|
||||
func (s *fireWeaponSystem) fire(weapon *component.WeaponComponent, position *component.PositionComponent, sprite *component.SpriteComponent, fireAngle float64) {
|
||||
if time.Since(weapon.LastFire) < weapon.FireRate {
|
||||
return
|
||||
}
|
||||
|
||||
weapon.Ammo--
|
||||
weapon.LastFire = time.Now()
|
||||
|
||||
speedX := math.Cos(fireAngle) * -weapon.BulletSpeed
|
||||
speedY := math.Sin(fireAngle) * -weapon.BulletSpeed
|
||||
|
||||
bullet := entity.NewBullet(position.X, position.Y, speedX, speedY)
|
||||
offsetX := 8.0
|
||||
if sprite.HorizontalFlip {
|
||||
offsetX = -24
|
||||
}
|
||||
const bulletOffsetY = -5
|
||||
bullet := entity.NewBullet(position.X+offsetX, position.Y+bulletOffsetY, speedX, speedY)
|
||||
_ = bullet
|
||||
}
|
||||
|
||||
func (s *fireWeaponSystem) Update(ctx *gohan.Context) error {
|
||||
return nil // TODO
|
||||
|
||||
weapon := component.Weapon(ctx)
|
||||
|
||||
if weapon.Ammo <= 0 {
|
||||
if !weapon.Equipped {
|
||||
return nil
|
||||
}
|
||||
|
||||
position := component.Position(ctx)
|
||||
|
||||
if ebiten.IsMouseButtonPressed(ebiten.MouseButtonLeft) {
|
||||
cursorX, cursorY := ebiten.CursorPosition()
|
||||
fireAngle := angle(position.X, position.Y, float64(cursorX), float64(cursorY))
|
||||
s.fire(weapon, position, fireAngle)
|
||||
}
|
||||
|
||||
switch {
|
||||
case ebiten.IsKeyPressed(ebiten.KeyLeft) && ebiten.IsKeyPressed(ebiten.KeyUp):
|
||||
s.fire(weapon, position, math.Pi/4)
|
||||
case ebiten.IsKeyPressed(ebiten.KeyLeft) && ebiten.IsKeyPressed(ebiten.KeyDown):
|
||||
s.fire(weapon, position, -math.Pi/4)
|
||||
case ebiten.IsKeyPressed(ebiten.KeyRight) && ebiten.IsKeyPressed(ebiten.KeyUp):
|
||||
s.fire(weapon, position, math.Pi*.75)
|
||||
case ebiten.IsKeyPressed(ebiten.KeyRight) && ebiten.IsKeyPressed(ebiten.KeyDown):
|
||||
s.fire(weapon, position, -math.Pi*.75)
|
||||
case ebiten.IsKeyPressed(ebiten.KeyLeft):
|
||||
s.fire(weapon, position, 0)
|
||||
case ebiten.IsKeyPressed(ebiten.KeyRight):
|
||||
s.fire(weapon, position, math.Pi)
|
||||
case ebiten.IsKeyPressed(ebiten.KeyUp):
|
||||
s.fire(weapon, position, math.Pi/2)
|
||||
case ebiten.IsKeyPressed(ebiten.KeyDown):
|
||||
s.fire(weapon, position, -math.Pi/2)
|
||||
if ebiten.IsKeyPressed(ebiten.KeyL) {
|
||||
position := component.Position(ctx)
|
||||
sprite := component.Sprite(ctx)
|
||||
fireAngle := math.Pi
|
||||
if sprite.HorizontalFlip {
|
||||
fireAngle = 0
|
||||
}
|
||||
s.fire(weapon, position, sprite, fireAngle)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package system
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"time"
|
||||
|
@ -89,27 +90,33 @@ func (s *playerMoveSystem) Update(ctx *gohan.Context) error {
|
|||
log.Printf("Spawn point set to %.0f,%.0f", world.World.SpawnX, world.World.SpawnY)
|
||||
return nil
|
||||
}
|
||||
if ebiten.IsKeyPressed(ebiten.KeyControl) && inpututil.IsKeyJustPressed(ebiten.KeyK) {
|
||||
if world.World.Keys < 3 {
|
||||
world.World.Keys++
|
||||
}
|
||||
world.World.SetMessage(fmt.Sprintf("YOU NOW HAVE %d KEYS.", world.World.Keys))
|
||||
return nil
|
||||
}
|
||||
|
||||
if world.World.MessageVisible {
|
||||
if inpututil.IsKeyJustPressed(ebiten.KeyEnter) {
|
||||
world.World.MessageVisible = false
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
setWalkFrames := func() {
|
||||
if world.World.NoClip {
|
||||
return
|
||||
}
|
||||
sprite := component.Sprite(ctx)
|
||||
if s.lastWalkDirL {
|
||||
sprite.Frames = []*ebiten.Image{
|
||||
asset.PlayerSS.WalkL1,
|
||||
asset.PlayerSS.IdleL,
|
||||
asset.PlayerSS.WalkL2,
|
||||
asset.PlayerSS.IdleL,
|
||||
}
|
||||
} else {
|
||||
sprite.Frames = []*ebiten.Image{
|
||||
asset.PlayerSS.WalkR1,
|
||||
asset.PlayerSS.IdleR,
|
||||
asset.PlayerSS.WalkR2,
|
||||
asset.PlayerSS.IdleR,
|
||||
}
|
||||
sprite.Frames = []*ebiten.Image{
|
||||
asset.PlayerSS.WalkR1,
|
||||
asset.PlayerSS.IdleR,
|
||||
asset.PlayerSS.WalkR2,
|
||||
asset.PlayerSS.IdleR,
|
||||
}
|
||||
sprite.HorizontalFlip = s.lastWalkDirL
|
||||
sprite.NumFrames = 4
|
||||
sprite.FrameTime = 150 * time.Millisecond
|
||||
}
|
||||
|
@ -117,19 +124,12 @@ func (s *playerMoveSystem) Update(ctx *gohan.Context) error {
|
|||
setJumpAndIdleFrames := func() {
|
||||
sprite := component.Sprite(ctx)
|
||||
sprite.NumFrames = 0
|
||||
if s.lastWalkDirL {
|
||||
if (s.movement.OnGround == -1 && s.movement.OnLadder == -1) || s.movement.Jumping || world.World.NoClip {
|
||||
sprite.Image = asset.PlayerSS.WalkL2
|
||||
} else {
|
||||
sprite.Image = asset.PlayerSS.IdleL
|
||||
}
|
||||
if (s.movement.OnGround == -1 && s.movement.OnLadder == -1) || s.movement.Jumping || world.World.NoClip {
|
||||
sprite.Image = asset.PlayerSS.WalkR2
|
||||
} else {
|
||||
if (s.movement.OnGround == -1 && s.movement.OnLadder == -1) || s.movement.Jumping || world.World.NoClip {
|
||||
sprite.Image = asset.PlayerSS.WalkR2
|
||||
} else {
|
||||
sprite.Image = asset.PlayerSS.IdleR
|
||||
}
|
||||
sprite.Image = asset.PlayerSS.IdleR
|
||||
}
|
||||
sprite.HorizontalFlip = s.lastWalkDirL
|
||||
}
|
||||
|
||||
// Rewind time.
|
||||
|
@ -237,11 +237,8 @@ func (s *playerMoveSystem) Update(ctx *gohan.Context) error {
|
|||
// Duck and look down.
|
||||
sprite := component.Sprite(ctx)
|
||||
sprite.NumFrames = 0
|
||||
if s.lastWalkDirL {
|
||||
sprite.Image = asset.PlayerSS.DuckL
|
||||
} else {
|
||||
sprite.Image = asset.PlayerSS.DuckR
|
||||
}
|
||||
sprite.Image = asset.PlayerSS.DuckR
|
||||
sprite.HorizontalFlip = s.lastWalkDirL
|
||||
walkKeyPressed = true
|
||||
|
||||
if world.World.DuckStart == -1 {
|
||||
|
@ -298,11 +295,12 @@ func (s *playerMoveSystem) Update(ctx *gohan.Context) error {
|
|||
if !world.World.NoClip {
|
||||
sprite := component.Sprite(ctx)
|
||||
sprite.Frames = []*ebiten.Image{
|
||||
asset.PlayerSS.WalkL1,
|
||||
asset.PlayerSS.IdleL,
|
||||
asset.PlayerSS.WalkL2,
|
||||
asset.PlayerSS.IdleL,
|
||||
asset.PlayerSS.WalkR1,
|
||||
asset.PlayerSS.IdleR,
|
||||
asset.PlayerSS.WalkR2,
|
||||
asset.PlayerSS.IdleR,
|
||||
}
|
||||
sprite.HorizontalFlip = true
|
||||
sprite.NumFrames = 4
|
||||
sprite.FrameTime = 150 * time.Millisecond
|
||||
}
|
||||
|
@ -327,6 +325,7 @@ func (s *playerMoveSystem) Update(ctx *gohan.Context) error {
|
|||
asset.PlayerSS.WalkR2,
|
||||
asset.PlayerSS.IdleR,
|
||||
}
|
||||
sprite.HorizontalFlip = false
|
||||
sprite.NumFrames = 4
|
||||
sprite.FrameTime = 150 * time.Millisecond
|
||||
}
|
||||
|
@ -373,7 +372,7 @@ func (s *playerMoveSystem) Update(ctx *gohan.Context) error {
|
|||
}
|
||||
|
||||
if world.World.Levitating {
|
||||
if ebiten.IsKeyPressed(ebiten.KeyW) {
|
||||
if ebiten.IsKeyPressed(ebiten.KeyJ) {
|
||||
if velocity.Y > -maxLevitateSpeed {
|
||||
velocity.Y -= moveSpeed
|
||||
}
|
||||
|
|
|
@ -1,12 +1,14 @@
|
|||
package system
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"image"
|
||||
"image/color"
|
||||
"math"
|
||||
"time"
|
||||
|
||||
"code.rocketnine.space/tslocum/gohan"
|
||||
"code.rocketnine.space/tslocum/monovania/asset"
|
||||
"code.rocketnine.space/tslocum/monovania/component"
|
||||
"code.rocketnine.space/tslocum/monovania/engine"
|
||||
"code.rocketnine.space/tslocum/monovania/world"
|
||||
|
@ -218,7 +220,9 @@ func (_ *MovementSystem) Needs() []gohan.ComponentID {
|
|||
}
|
||||
|
||||
func (_ *MovementSystem) Uses() []gohan.ComponentID {
|
||||
return nil
|
||||
return []gohan.ComponentID{
|
||||
component.WeaponComponentID,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *MovementSystem) checkFire(ctx *gohan.Context, r image.Rectangle) {
|
||||
|
@ -234,18 +238,56 @@ func (s *MovementSystem) checkFire(ctx *gohan.Context, r image.Rectangle) {
|
|||
}
|
||||
}
|
||||
|
||||
func (s *MovementSystem) checkTriggers(r image.Rectangle) {
|
||||
func (s *MovementSystem) checkTriggers(ctx *gohan.Context, r image.Rectangle) {
|
||||
for i, triggerRect := range world.World.TriggerRects {
|
||||
if r.Overlaps(triggerRect) {
|
||||
switch world.World.TriggerNames[i] {
|
||||
case "DOUBLEJUMP":
|
||||
world.World.CanDoubleJump = true
|
||||
|
||||
world.World.SetMessage("<J> TO DOUBLE JUMP.")
|
||||
case "DASH":
|
||||
world.World.CanDash = true
|
||||
|
||||
world.World.SetMessage("<K> TO DASH.")
|
||||
case "LEVITATE":
|
||||
world.World.CanLevitate = true
|
||||
|
||||
world.World.SetMessage("<J> TO LEVITATE AFTER DOUBLE JUMPING.")
|
||||
case "KEY":
|
||||
world.World.Keys++
|
||||
|
||||
if world.World.Keys == 1 {
|
||||
world.World.SetMessage("FIRST EXIT KEY FOUND.")
|
||||
} else if world.World.Keys == 1 {
|
||||
world.World.SetMessage("SECOND EXIT KEY FOUND.")
|
||||
} else {
|
||||
world.World.SetMessage("FINAL EXIT KEY FOUND.")
|
||||
}
|
||||
case "UZI":
|
||||
weapon := component.Weapon(ctx)
|
||||
weapon.Equipped = true
|
||||
|
||||
sprite := engine.Engine.Component(world.World.Player, component.SpriteComponentID).(*component.SpriteComponent)
|
||||
sprite.Overlay = asset.ImgUzi
|
||||
sprite.OverlayX = 6
|
||||
sprite.OverlayY = 7
|
||||
|
||||
world.World.SetMessage("<L> TO FIRE.")
|
||||
case "EXIT":
|
||||
if world.World.Keys < 3 {
|
||||
position := component.Position(ctx)
|
||||
velocity := component.Velocity(ctx)
|
||||
position.X = position.X + 0.25
|
||||
velocity.X = 0
|
||||
|
||||
world.World.SetMessage("THIS DOOR REQUIRES THREE KEYS.")
|
||||
return
|
||||
}
|
||||
|
||||
world.World.SetMessage("GAME OVER. YOU WIN!")
|
||||
default:
|
||||
panic("unknown trigger " + world.World.TriggerNames[i])
|
||||
world.World.SetMessage(fmt.Sprintf("UNKNOWN TRIGGER '%s'.", world.World.TriggerNames[i]))
|
||||
}
|
||||
|
||||
// Remove trigger.
|
||||
|
@ -254,8 +296,6 @@ func (s *MovementSystem) checkTriggers(r image.Rectangle) {
|
|||
world.World.TriggerRects = append(world.World.TriggerRects[:i], world.World.TriggerRects[i+1:]...)
|
||||
world.World.TriggerEntities = append(world.World.TriggerEntities[:i], world.World.TriggerEntities[i+1:]...)
|
||||
world.World.TriggerNames = append(world.World.TriggerNames[:i], world.World.TriggerNames[i+1:]...)
|
||||
|
||||
// TODO Show ability info and usage popup.
|
||||
return
|
||||
}
|
||||
}
|
||||
|
@ -263,11 +303,11 @@ func (s *MovementSystem) checkTriggers(r image.Rectangle) {
|
|||
|
||||
func (s *MovementSystem) checkCollisions(ctx *gohan.Context, r image.Rectangle) {
|
||||
s.checkFire(ctx, r)
|
||||
s.checkTriggers(r)
|
||||
s.checkTriggers(ctx, r)
|
||||
}
|
||||
|
||||
func (s *MovementSystem) Update(ctx *gohan.Context) error {
|
||||
if world.World.GameOver {
|
||||
if world.World.MessageVisible || world.World.GameOver {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -283,17 +323,19 @@ func (s *MovementSystem) Update(ctx *gohan.Context) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// TODO apply left and right X collision adjustments (too large, can hang entirely off edge of cliff)
|
||||
if ctx.Entity == world.World.Player {
|
||||
// TODO apply left and right X collision adjustments (too large, can hang entirely off edge of cliff)
|
||||
|
||||
onLadder := -1
|
||||
playerRect := image.Rect(int(position.X), int(position.Y), int(position.X)+16, int(position.Y)+16)
|
||||
for i, rect := range s.ladderRects {
|
||||
if playerRect.Overlaps(rect) {
|
||||
onLadder = i
|
||||
break
|
||||
onLadder := -1
|
||||
playerRect := image.Rect(int(position.X), int(position.Y), int(position.X)+16, int(position.Y)+16)
|
||||
for i, rect := range s.ladderRects {
|
||||
if playerRect.Overlaps(rect) {
|
||||
onLadder = i
|
||||
break
|
||||
}
|
||||
}
|
||||
s.OnLadder = onLadder
|
||||
}
|
||||
s.OnLadder = onLadder
|
||||
|
||||
// Apply weight and gravity.
|
||||
|
||||
|
@ -320,89 +362,134 @@ func (s *MovementSystem) Update(ctx *gohan.Context) error {
|
|||
}
|
||||
|
||||
vx, vy := velocity.X, velocity.Y
|
||||
if world.World.Debug > 0 && ebiten.IsKeyPressed(ebiten.KeyShift) {
|
||||
if (world.World.NoClip || world.World.Debug > 0) && ebiten.IsKeyPressed(ebiten.KeyShift) {
|
||||
vx, vy = vx*2, vy*2
|
||||
}
|
||||
|
||||
// Check collisions.
|
||||
|
||||
var (
|
||||
collideX = -1
|
||||
collideY = -1
|
||||
collideXY = -1
|
||||
collideG = -1
|
||||
)
|
||||
const gravityThreshold = 4
|
||||
playerRectX := image.Rect(int(position.X+vx), int(position.Y), int(position.X+vx)+16, int(position.Y)+17)
|
||||
playerRectY := image.Rect(int(position.X), int(position.Y+vy), int(position.X)+16, int(position.Y+vy)+17)
|
||||
playerRectXY := image.Rect(int(position.X+vx), int(position.Y+vy), int(position.X+vx)+16, int(position.Y+vy)+17)
|
||||
playerRectG := image.Rect(int(position.X), int(position.Y+gravityThreshold), int(position.X)+16, int(position.Y+gravityThreshold)+17)
|
||||
for i, rect := range s.collisionRects {
|
||||
if world.World.NoClip {
|
||||
continue
|
||||
}
|
||||
if playerRectX.Overlaps(rect) {
|
||||
collideX = i
|
||||
s.checkCollisions(ctx, playerRectX)
|
||||
}
|
||||
if playerRectY.Overlaps(rect) {
|
||||
collideY = i
|
||||
s.checkCollisions(ctx, playerRectY)
|
||||
}
|
||||
if playerRectXY.Overlaps(rect) {
|
||||
collideXY = i
|
||||
s.checkCollisions(ctx, playerRectXY)
|
||||
}
|
||||
if playerRectG.Overlaps(rect) {
|
||||
collideG = i
|
||||
s.checkCollisions(ctx, playerRectG)
|
||||
}
|
||||
}
|
||||
if collideXY == -1 {
|
||||
position.X, position.Y = position.X+vx, position.Y+vy
|
||||
} else if collideX == -1 {
|
||||
position.X = position.X + vx
|
||||
velocity.Y = 0
|
||||
} else if collideY == -1 {
|
||||
position.Y = position.Y + vy
|
||||
velocity.X = 0
|
||||
} else {
|
||||
velocity.X, velocity.Y = 0, 0
|
||||
}
|
||||
s.OnGround = collideG
|
||||
if s.OnGround != -1 || s.OnLadder != -1 {
|
||||
// Reset jump counter.
|
||||
if world.World.Jumps != 0 && time.Since(s.LastJump) >= 50*time.Millisecond {
|
||||
world.World.Jumps = 0
|
||||
}
|
||||
// Reset dash counter.
|
||||
if world.World.Dashes != 0 {
|
||||
world.World.Dashes = 0
|
||||
}
|
||||
}
|
||||
|
||||
// Remember positions to support rewinding time.
|
||||
const recordTicks = 144 / 2
|
||||
if ctx.Entity == world.World.Player {
|
||||
if world.World.Rewinding {
|
||||
s.playerPositionTicks = 0
|
||||
} else {
|
||||
s.playerPositionTicks++
|
||||
if s.playerPositionTicks >= recordTicks || !s.recordedPosition {
|
||||
s.RecordPosition(position)
|
||||
s.playerPositionTicks = 0
|
||||
s.recordedPosition = true
|
||||
var (
|
||||
collideX = -1
|
||||
collideY = -1
|
||||
collideXY = -1
|
||||
collideG = -1
|
||||
)
|
||||
const gravityThreshold = 4
|
||||
playerRectX := image.Rect(int(position.X+vx), int(position.Y+1), int(position.X+vx)+16, int(position.Y)+17)
|
||||
playerRectY := image.Rect(int(position.X), int(position.Y+1+vy), int(position.X)+16, int(position.Y+vy)+17)
|
||||
playerRectXY := image.Rect(int(position.X+vx), int(position.Y+1+vy), int(position.X+vx)+16, int(position.Y+vy)+17)
|
||||
playerRectG := image.Rect(int(position.X), int(position.Y+1+gravityThreshold), int(position.X)+16, int(position.Y+gravityThreshold)+17)
|
||||
if !world.World.NoClip {
|
||||
for i, rect := range s.collisionRects {
|
||||
if playerRectX.Overlaps(rect) {
|
||||
collideX = i
|
||||
s.checkCollisions(ctx, playerRectX)
|
||||
}
|
||||
if playerRectY.Overlaps(rect) {
|
||||
collideY = i
|
||||
s.checkCollisions(ctx, playerRectY)
|
||||
}
|
||||
if playerRectXY.Overlaps(rect) {
|
||||
collideXY = i
|
||||
s.checkCollisions(ctx, playerRectXY)
|
||||
}
|
||||
if playerRectG.Overlaps(rect) {
|
||||
collideG = i
|
||||
s.checkCollisions(ctx, playerRectG)
|
||||
}
|
||||
}
|
||||
for i, rect := range world.World.DestructibleRects {
|
||||
if playerRectX.Overlaps(rect) {
|
||||
collideX = i
|
||||
s.checkCollisions(ctx, playerRectX)
|
||||
}
|
||||
if playerRectY.Overlaps(rect) {
|
||||
collideY = i
|
||||
s.checkCollisions(ctx, playerRectY)
|
||||
}
|
||||
if playerRectXY.Overlaps(rect) {
|
||||
collideXY = i
|
||||
s.checkCollisions(ctx, playerRectXY)
|
||||
}
|
||||
if playerRectG.Overlaps(rect) {
|
||||
collideG = i
|
||||
s.checkCollisions(ctx, playerRectG)
|
||||
}
|
||||
}
|
||||
}
|
||||
if collideXY == -1 {
|
||||
position.X, position.Y = position.X+vx, position.Y+vy
|
||||
} else if collideX == -1 {
|
||||
position.X = position.X + vx
|
||||
velocity.Y = 0
|
||||
} else if collideY == -1 {
|
||||
position.Y = position.Y + vy
|
||||
velocity.X = 0
|
||||
} else {
|
||||
velocity.X, velocity.Y = 0, 0
|
||||
}
|
||||
s.OnGround = collideG
|
||||
if s.OnGround != -1 || s.OnLadder != -1 {
|
||||
// Reset jump counter.
|
||||
if world.World.Jumps != 0 && time.Since(s.LastJump) >= 50*time.Millisecond {
|
||||
world.World.Jumps = 0
|
||||
}
|
||||
// Reset dash counter.
|
||||
if world.World.Dashes != 0 {
|
||||
world.World.Dashes = 0
|
||||
}
|
||||
}
|
||||
|
||||
// Remember positions to support rewinding time.
|
||||
const recordTicks = 144 / 2
|
||||
if ctx.Entity == world.World.Player {
|
||||
if world.World.Rewinding {
|
||||
s.playerPositionTicks = 0
|
||||
} else {
|
||||
s.playerPositionTicks++
|
||||
if s.playerPositionTicks >= recordTicks || !s.recordedPosition {
|
||||
s.RecordPosition(position)
|
||||
s.playerPositionTicks = 0
|
||||
s.recordedPosition = true
|
||||
}
|
||||
}
|
||||
}
|
||||
// TODO: Does this use enough memory to require pruning positions?
|
||||
|
||||
// Update debug rects.
|
||||
|
||||
if s.OnGround != lastOnGround || s.OnLadder != lastOnLadder {
|
||||
s.UpdateDebugCollisionRects()
|
||||
}
|
||||
} else {
|
||||
position.X, position.Y = position.X+vx, position.Y+vy
|
||||
|
||||
bulletOffsetX := 0.0
|
||||
bulletOffsetY := 1.0
|
||||
bulletWidth := 1.0
|
||||
|
||||
bulletRectSmall := image.Rect(int(position.X+bulletOffsetX), int(position.Y+bulletOffsetY), int(position.X+bulletOffsetX+bulletWidth), int(position.Y+bulletOffsetY+bulletWidth))
|
||||
bulletWidth = 5.0
|
||||
bulletRectLarge := image.Rect(int(position.X+bulletOffsetX), int(position.Y+bulletOffsetY), int(position.X+bulletOffsetX+bulletWidth), int(position.Y+bulletOffsetY+bulletWidth))
|
||||
for i, r := range world.World.DestructibleRects {
|
||||
if r.Overlaps(bulletRectSmall) {
|
||||
// Hit destructible.
|
||||
ctx.RemoveEntity()
|
||||
engine.Engine.RemoveEntity(world.World.DestructibleEntities[i])
|
||||
world.World.DestructibleRects = append(world.World.DestructibleRects[:i], world.World.DestructibleRects[i+1:]...)
|
||||
world.World.DestructibleEntities = append(world.World.DestructibleEntities[:i], world.World.DestructibleEntities[i+1:]...)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
for _, r := range s.collisionRects {
|
||||
if r.Overlaps(bulletRectSmall) {
|
||||
// Hit wall.
|
||||
ctx.RemoveEntity()
|
||||
return nil
|
||||
}
|
||||
}
|
||||
_ = bulletRectLarge
|
||||
}
|
||||
// TODO: Does this use enough memory to require pruning positions?
|
||||
|
||||
// Update debug rects.
|
||||
|
||||
if s.OnGround != lastOnGround || s.OnLadder != lastOnLadder {
|
||||
s.UpdateDebugCollisionRects()
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@ import (
|
|||
"time"
|
||||
|
||||
"code.rocketnine.space/tslocum/gohan"
|
||||
"code.rocketnine.space/tslocum/monovania/asset"
|
||||
"code.rocketnine.space/tslocum/monovania/component"
|
||||
"code.rocketnine.space/tslocum/monovania/engine"
|
||||
"code.rocketnine.space/tslocum/monovania/world"
|
||||
|
@ -130,7 +131,7 @@ func (s *RenderSystem) Draw(ctx *gohan.Context, screen *ebiten.Image) error {
|
|||
position := component.Position(ctx)
|
||||
sprite := component.Sprite(ctx)
|
||||
|
||||
if sprite.NumFrames > 0 && time.Since(sprite.LastFrame) > sprite.FrameTime {
|
||||
if sprite.NumFrames > 0 && !world.World.MessageVisible && time.Since(sprite.LastFrame) > sprite.FrameTime {
|
||||
sprite.Frame++
|
||||
if sprite.Frame >= sprite.NumFrames {
|
||||
sprite.Frame = 0
|
||||
|
@ -144,8 +145,17 @@ func (s *RenderSystem) Draw(ctx *gohan.Context, screen *ebiten.Image) error {
|
|||
colorScale = sprite.ColorScale
|
||||
}
|
||||
|
||||
// TODO
|
||||
var drawn int
|
||||
drawn += s.renderSprite(position.X+world.World.OffsetX, position.Y+world.World.OffsetY, 0, 0, 0, 1.0, colorScale, 1.0, sprite.HorizontalFlip, sprite.VerticalFlip, sprite.Image, screen)
|
||||
s.renderSprite(position.X+world.World.OffsetX, position.Y+world.World.OffsetY, 0, 0, 0, 1.0, colorScale, 1.0, sprite.HorizontalFlip, sprite.VerticalFlip, sprite.Image, screen)
|
||||
if sprite.Overlay != nil {
|
||||
offsetX := sprite.OverlayX
|
||||
if sprite.HorizontalFlip {
|
||||
offsetX *= -1
|
||||
}
|
||||
offsetY := sprite.OverlayY
|
||||
if sprite.Image == asset.PlayerSS.WalkR1 || sprite.Image == asset.PlayerSS.WalkR2 {
|
||||
offsetY -= 1
|
||||
}
|
||||
s.renderSprite(position.X+world.World.OffsetX+offsetX, position.Y+world.World.OffsetY+offsetY, 0, 0, 0, 1.0, colorScale, 1.0, sprite.HorizontalFlip, sprite.VerticalFlip, sprite.Overlay, screen)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -6,28 +6,29 @@ import (
|
|||
_ "image/png"
|
||||
"strings"
|
||||
|
||||
"golang.org/x/image/colornames"
|
||||
|
||||
"code.rocketnine.space/tslocum/gohan"
|
||||
"code.rocketnine.space/tslocum/monovania/component"
|
||||
"code.rocketnine.space/tslocum/monovania/world"
|
||||
"github.com/hajimehoshi/ebiten/v2"
|
||||
"github.com/hajimehoshi/ebiten/v2/ebitenutil"
|
||||
"golang.org/x/image/colornames"
|
||||
)
|
||||
|
||||
type RenderMessageSystem struct {
|
||||
player gohan.Entity
|
||||
op *ebiten.DrawImageOptions
|
||||
logoImg *ebiten.Image
|
||||
debugImg *ebiten.Image
|
||||
player gohan.Entity
|
||||
op *ebiten.DrawImageOptions
|
||||
logoImg *ebiten.Image
|
||||
msgImg *ebiten.Image
|
||||
tmpImg *ebiten.Image
|
||||
}
|
||||
|
||||
func NewRenderMessageSystem(player gohan.Entity) *RenderMessageSystem {
|
||||
s := &RenderMessageSystem{
|
||||
player: player,
|
||||
op: &ebiten.DrawImageOptions{},
|
||||
logoImg: ebiten.NewImage(1, 1),
|
||||
debugImg: ebiten.NewImage(200, 200),
|
||||
player: player,
|
||||
op: &ebiten.DrawImageOptions{},
|
||||
logoImg: ebiten.NewImage(1, 1),
|
||||
msgImg: ebiten.NewImage(1, 1),
|
||||
tmpImg: ebiten.NewImage(200, 200),
|
||||
}
|
||||
|
||||
return s
|
||||
|
@ -50,8 +51,31 @@ func (s *RenderMessageSystem) Update(_ *gohan.Context) error {
|
|||
}
|
||||
|
||||
func (s *RenderMessageSystem) Draw(ctx *gohan.Context, screen *ebiten.Image) error {
|
||||
if world.World.GameOver {
|
||||
// Draw game over screen.
|
||||
if ctx.Entity == world.World.Player {
|
||||
screen.Fill(colornames.Darkred)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
if !world.World.MessageVisible {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Draw message.
|
||||
if world.World.MessageUpdated {
|
||||
s.drawMessage()
|
||||
}
|
||||
bounds := s.msgImg.Bounds()
|
||||
x := (float64(world.World.ScreenW) / 2) - (float64(bounds.Dx()) / 2)
|
||||
y := (float64(world.World.ScreenH) / 2) - float64(bounds.Dy()) - 8
|
||||
s.op.GeoM.Reset()
|
||||
s.op.GeoM.Translate(x, y)
|
||||
screen.DrawImage(s.msgImg, s.op)
|
||||
|
||||
// Draw logo.
|
||||
if !world.World.GameStarted || world.World.FadingIn {
|
||||
// Draw logo.
|
||||
if ctx.Entity == world.World.Player {
|
||||
var alpha float64
|
||||
if !world.World.GameStarted {
|
||||
|
@ -66,33 +90,23 @@ func (s *RenderMessageSystem) Draw(ctx *gohan.Context, screen *ebiten.Image) err
|
|||
if alpha > 1 {
|
||||
alpha = 1
|
||||
}
|
||||
op := &ebiten.DrawImageOptions{}
|
||||
s.op.GeoM.Reset()
|
||||
if !world.World.GameStarted {
|
||||
op.ColorM.ChangeHSV(0, 1, alpha)
|
||||
s.op.ColorM.ChangeHSV(0, 1, alpha)
|
||||
} else {
|
||||
op.ColorM.Scale(1, 1, 1, alpha)
|
||||
s.op.ColorM.Scale(1, 1, 1, alpha)
|
||||
}
|
||||
screen.DrawImage(s.logoImg, op)
|
||||
screen.DrawImage(s.logoImg, s.op)
|
||||
s.op.ColorM.Reset()
|
||||
}
|
||||
if !world.World.GameStarted {
|
||||
return nil
|
||||
}
|
||||
} else if world.World.GameOver {
|
||||
// Draw game over screen.
|
||||
if ctx.Entity == world.World.Player {
|
||||
screen.Fill(colornames.Darkred)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
if !world.World.MessageVisible {
|
||||
return nil
|
||||
}
|
||||
func (s *RenderMessageSystem) drawMessage() {
|
||||
message := world.World.MessageText + "\n\n<ENTER> TO CONTINUE."
|
||||
|
||||
/*position := component.Position(ctx)
|
||||
velocity := component.Velocity(ctx)*/
|
||||
|
||||
split := strings.Split(world.World.MessageText, "\n")
|
||||
split := strings.Split(message, "\n")
|
||||
width := 0
|
||||
for _, line := range split {
|
||||
lineSize := len(line) * 12
|
||||
|
@ -103,19 +117,19 @@ func (s *RenderMessageSystem) Draw(ctx *gohan.Context, screen *ebiten.Image) err
|
|||
height := len(split) * 32
|
||||
|
||||
const padding = 8
|
||||
width, height = width+padding*2, height+padding*2
|
||||
|
||||
x, y := (world.World.ScreenW-width)/2, (world.World.ScreenH-height)/2
|
||||
s.msgImg = ebiten.NewImage(width, height)
|
||||
s.msgImg.Fill(color.RGBA{17, 17, 17, 255})
|
||||
|
||||
screen.SubImage(image.Rect(x-padding, y-padding, x+width+padding, y+height+padding)).(*ebiten.Image).Fill(color.Black)
|
||||
|
||||
s.debugImg.Clear()
|
||||
s.tmpImg.Clear()
|
||||
s.tmpImg = ebiten.NewImage(width*2, height*2)
|
||||
s.op.GeoM.Reset()
|
||||
s.op.GeoM.Scale(2, 2)
|
||||
s.op.GeoM.Translate(float64(world.World.ScreenW-width)/2, float64(world.World.ScreenH-height)/2)
|
||||
ebitenutil.DebugPrint(s.debugImg, world.World.MessageText)
|
||||
screen.DrawImage(s.debugImg, s.op)
|
||||
|
||||
return nil
|
||||
s.op.GeoM.Translate(float64(padding), float64(padding))
|
||||
ebitenutil.DebugPrint(s.tmpImg, message)
|
||||
s.msgImg.DrawImage(s.tmpImg, s.op)
|
||||
s.op.ColorM.Reset()
|
||||
}
|
||||
|
||||
func (s *RenderMessageSystem) drawLogo() {
|
||||
|
@ -129,7 +143,7 @@ func (s *RenderMessageSystem) drawLogo() {
|
|||
logoOffset := int(float64(logoSize) * (4.0 / 9.0))
|
||||
tailWidth := int(float64(logoSize) * (5.0 / 9.0))
|
||||
x := (world.World.ScreenW / 2) - (totalSize / 2)
|
||||
y := (world.World.ScreenH / 2)
|
||||
y := world.World.ScreenH / 2
|
||||
for i := 0; i < 3; i++ {
|
||||
offset := i * logoOffset
|
||||
s.logoImg.SubImage(image.Rect(x+offset, y-offset, x+logoSize+offset, y+logoSize-offset)).(*ebiten.Image).Fill(logoColor)
|
||||
|
@ -149,4 +163,5 @@ func (s *RenderMessageSystem) drawLogo() {
|
|||
|
||||
func (s *RenderMessageSystem) SizeUpdated() {
|
||||
s.drawLogo()
|
||||
s.drawMessage()
|
||||
}
|
||||
|
|
|
@ -66,13 +66,17 @@ type GameWorld struct {
|
|||
Rewinding bool
|
||||
|
||||
MessageVisible bool
|
||||
MessageUpdated bool
|
||||
MessageTitle string
|
||||
MessageText string
|
||||
|
||||
TriggerRects []image.Rectangle
|
||||
TriggerEntities []gohan.Entity
|
||||
TriggerRects []image.Rectangle
|
||||
TriggerNames []string
|
||||
|
||||
DestructibleEntities []gohan.Entity
|
||||
DestructibleRects []image.Rectangle
|
||||
|
||||
DisableEsc bool
|
||||
}
|
||||
|
||||
|
@ -221,7 +225,7 @@ func LoadMap(filePath string) {
|
|||
for _, grp := range World.ObjectGroups {
|
||||
if grp.Name == "PLAYERSPAWN" {
|
||||
for _, obj := range grp.Objects {
|
||||
World.SpawnX, World.SpawnY = obj.X, obj.Y-1
|
||||
World.SpawnX, World.SpawnY = obj.X, obj.Y-0.1
|
||||
}
|
||||
break
|
||||
}
|
||||
|
@ -232,7 +236,7 @@ func LoadMap(filePath string) {
|
|||
}
|
||||
if grp.Name == "TEMPSPAWN" {
|
||||
for _, obj := range grp.Objects {
|
||||
World.SpawnX, World.SpawnY = obj.X, obj.Y-1
|
||||
World.SpawnX, World.SpawnY = obj.X, obj.Y-0.1
|
||||
}
|
||||
break
|
||||
}
|
||||
|
@ -244,10 +248,6 @@ func LoadMap(filePath string) {
|
|||
for _, grp := range World.ObjectGroups {
|
||||
if grp.Name == "TRIGGERS" {
|
||||
for _, obj := range grp.Objects {
|
||||
if obj.Name == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
mapTile := engine.Engine.NewEntity()
|
||||
engine.Engine.AddComponent(mapTile, &component.PositionComponent{
|
||||
X: obj.X,
|
||||
|
@ -261,7 +261,24 @@ func LoadMap(filePath string) {
|
|||
World.TriggerEntities = append(World.TriggerEntities, mapTile)
|
||||
World.TriggerRects = append(World.TriggerRects, ObjectToRect(obj))
|
||||
}
|
||||
break
|
||||
} else if grp.Name == "DESTRUCTIBLE" {
|
||||
continue // TODO Fix destructible environment rects
|
||||
|
||||
for _, obj := range grp.Objects {
|
||||
mapTile := engine.Engine.NewEntity()
|
||||
engine.Engine.AddComponent(mapTile, &component.PositionComponent{
|
||||
X: obj.X,
|
||||
Y: obj.Y - 16,
|
||||
})
|
||||
engine.Engine.AddComponent(mapTile, &component.SpriteComponent{
|
||||
Image: tileCache[obj.GID],
|
||||
})
|
||||
engine.Engine.AddComponent(mapTile, &component.DestructibleComponent{})
|
||||
|
||||
World.DestructibleEntities = append(World.DestructibleEntities, mapTile)
|
||||
r := image.Rect(int(obj.X), int(obj.Y-32), int(obj.X+16), int(obj.Y-16))
|
||||
World.DestructibleRects = append(World.DestructibleRects, r)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -270,3 +287,9 @@ func ObjectToRect(o *tiled.Object) image.Rectangle {
|
|||
x, y, w, h := int(o.X), int(o.Y), int(o.Width), int(o.Height)
|
||||
return image.Rect(x, y, x+w, y+h)
|
||||
}
|
||||
|
||||
func (w *GameWorld) SetMessage(message string) {
|
||||
w.MessageText = message
|
||||
w.MessageVisible = true
|
||||
w.MessageUpdated = true
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue