Skip to content

Commit

Permalink
move assets, fix 'deploy' builds
Browse files Browse the repository at this point in the history
  • Loading branch information
jcgraybill committed Apr 10, 2022
1 parent 38ef0b8 commit 6fd4923
Show file tree
Hide file tree
Showing 32 changed files with 93 additions and 89 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,5 @@ Built in [golang](https://go.dev/) using the [ebiten](https://ebiten.org/) 2D ga
```
git clone [email protected]:jcgraybill/it-costs-money.git
go mod tidy
go build
go build -tags "ebitensinglethread deploy"
```
8 changes: 5 additions & 3 deletions coin/coin.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
// TODO coin should be contained within level, since it's an actor
// Put coins and spawns in separate slices in "level", so you can scan through them without
// checking "kind"

package coin

Expand All @@ -9,7 +11,7 @@ import (
"github.com/hajimehoshi/ebiten/v2"
"github.com/hajimehoshi/ebiten/v2/audio"
"github.com/hajimehoshi/ebiten/v2/audio/wav"
"github.com/jcgraybill/it-costs-money/util"
"github.com/jcgraybill/it-costs-money/sys"
)

type Coin struct {
Expand All @@ -23,15 +25,15 @@ type Coin struct {

func New() Coin {
var c Coin
coinSprites := util.LoadSpriteSheet("assets/coin.png")
coinSprites := sys.LoadSpriteSheet("assets/coin.png")
c.Slides = coinSprites[1:7]
c.NumSlides = 6
c.AnimationSpeed = 10
c.sampleRate = 48000
c.audioContext = audio.NewContext(c.sampleRate)

for i := 0; i < 5; i++ {
audioBytes, err := util.GameData(fmt.Sprintf("assets/Coins_Grab_0%d.wav", i))
audioBytes, err := sys.GameData(fmt.Sprintf("assets/Coins_Grab_0%d.wav", i))
if err != nil {
panic(err)
}
Expand Down
4 changes: 2 additions & 2 deletions deploy.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@
package main

func levelEditor(g *Game) string {
return nil
}
return ""
}
18 changes: 9 additions & 9 deletions drawscreen.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,38 +5,38 @@ import (

"github.com/hajimehoshi/ebiten/v2"
"github.com/hajimehoshi/ebiten/v2/ebitenutil"
"github.com/jcgraybill/it-costs-money/util"
"github.com/jcgraybill/it-costs-money/sys"
)

func (g *Game) Draw(screen *ebiten.Image) {

// TODO objects should draw themselves - add a draw.go to coin, level, player
// Each returns an appropriate image
// Pass framebuffer for them to decorate

frameBuffer.Clear()
parallax(g.level.BgImage1, -g.player.X, 4)
parallax(g.level.BgImage2, -g.player.X, 3)
parallax(g.level.BgImage3, -g.player.X, 2)

viewPortOffset := g.player.X - (util.ScreenWidth/2 + util.FrameWidth/2)
levelViewFinder := image.Rect(viewPortOffset, 0, viewPortOffset+util.ScreenWidth, util.ScreenHeight)
viewPortOffset := g.player.X - (sys.ScreenWidth/2 + sys.FrameWidth/2)
levelViewFinder := image.Rect(viewPortOffset, 0, viewPortOffset+sys.ScreenWidth, sys.ScreenHeight)
frameBuffer.DrawImage(g.level.LevelBackgroundImage.SubImage(levelViewFinder).(*ebiten.Image), nil)
frameBuffer.DrawImage(g.level.LevelImage.SubImage(levelViewFinder).(*ebiten.Image), nil)

runnerOP := &ebiten.DrawImageOptions{}

if g.player.FacingLeft {
runnerOP.GeoM.Scale(-1, 1)
runnerOP.GeoM.Translate(util.FrameWidth, 0)
runnerOP.GeoM.Translate(sys.FrameWidth, 0)
}
runnerOP.GeoM.Translate(-float64(util.FrameWidth)/2, 0)
runnerOP.GeoM.Translate(util.ScreenWidth/2, float64(g.player.Y))
runnerOP.GeoM.Translate(-float64(sys.FrameWidth)/2, 0)
runnerOP.GeoM.Translate(sys.ScreenWidth/2, float64(g.player.Y))
i := (g.count / 5) % len(*g.player.Slides)

for _, actor := range g.level.Actors {
if actor.Exists {
if actor.Kind == "c" {
if actor.X > viewPortOffset || actor.X < viewPortOffset+util.ScreenWidth/2-util.FrameWidth {
if actor.X > viewPortOffset || actor.X < viewPortOffset+sys.ScreenWidth/2-sys.FrameWidth {
coinOp := &ebiten.DrawImageOptions{}
coinOp.GeoM.Translate(-float64(viewPortOffset-actor.X), float64(actor.Y))
frameBuffer.DrawImage(g.coin.Slides[(g.count/g.coin.AnimationSpeed)%g.coin.NumSlides], coinOp)
Expand All @@ -59,7 +59,7 @@ func parallax(image *ebiten.Image, offset int, speed int) {
op.GeoM.Translate(float64(position), 0)
frameBuffer.DrawImage(image, op)

for i := 0; position+i*panelWidth+panelWidth < util.ScreenWidth; i++ {
for i := 0; position+i*panelWidth+panelWidth < sys.ScreenWidth; i++ {
op.GeoM.Translate(float64(panelWidth), 0)
frameBuffer.DrawImage(image, op)
}
Expand Down
34 changes: 18 additions & 16 deletions gameloop.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import (

"github.com/hajimehoshi/ebiten/v2"
_ "github.com/jcgraybill/it-costs-money/player"
"github.com/jcgraybill/it-costs-money/util"
"github.com/jcgraybill/it-costs-money/sys"
)

func (g *Game) Update() error {
Expand All @@ -14,7 +14,9 @@ func (g *Game) Update() error {
g.player.Slides = &g.player.IdleFrames

//TODO if player is mid-jump, will get stuck hovering in the air
if g.player.X > g.level.LevelImage.Bounds().Dx()-util.ScreenWidth/2+util.FrameWidth/2-1 {
//Will require rearranging what order these checks happen in. What depends on what, or should pre-empt what?

if g.player.X > g.level.LevelImage.Bounds().Dx()-sys.ScreenWidth/2+sys.FrameWidth/2-1 {
message = fmt.Sprintf("Congratulations! You collected %d coins.\nPlease place them in the dumpster.", g.player.Coins)
return nil
}
Expand All @@ -25,27 +27,27 @@ func (g *Game) Update() error {

// Detect collisions
touchingGround := false
if _, _, _, a := g.level.LevelImage.At(g.player.X-util.FrameWidth/2, g.player.Y+util.FrameHeight).RGBA(); a > 0 {
if _, _, _, a := g.level.LevelImage.At(g.player.X-sys.FrameWidth/2, g.player.Y+sys.FrameHeight).RGBA(); a > 0 {
touchingGround = true
}

touchingLeft := false
if _, _, _, a := g.level.LevelImage.At(g.player.X-util.FrameWidth, g.player.Y+util.FrameHeight/2).RGBA(); a > 0 {
if _, _, _, a := g.level.LevelImage.At(g.player.X-sys.FrameWidth, g.player.Y+sys.FrameHeight/2).RGBA(); a > 0 {
touchingLeft = true
}

leftAdjacent := false
if _, _, _, a := g.level.LevelImage.At(g.player.X-util.FrameWidth-g.level.MoveSpeed, g.player.Y+util.FrameHeight/2).RGBA(); a > 0 {
if _, _, _, a := g.level.LevelImage.At(g.player.X-sys.FrameWidth-g.level.MoveSpeed, g.player.Y+sys.FrameHeight/2).RGBA(); a > 0 {
leftAdjacent = true
}

touchingRight := false
if _, _, _, a := g.level.LevelImage.At(g.player.X, g.player.Y+util.FrameHeight/2).RGBA(); a > 0 {
if _, _, _, a := g.level.LevelImage.At(g.player.X, g.player.Y+sys.FrameHeight/2).RGBA(); a > 0 {
touchingRight = true
}

rightAdjacent := false
if _, _, _, a := g.level.LevelImage.At(g.player.X+g.level.MoveSpeed, g.player.Y+util.FrameHeight/2).RGBA(); a > 0 {
if _, _, _, a := g.level.LevelImage.At(g.player.X+g.level.MoveSpeed, g.player.Y+sys.FrameHeight/2).RGBA(); a > 0 {
rightAdjacent = true
}

Expand All @@ -58,7 +60,7 @@ func (g *Game) Update() error {

if ebiten.IsKeyPressed(ebiten.KeySpace) || ebiten.IsKeyPressed(ebiten.KeyArrowUp) {
if g.player.TimeSinceLastJump+g.player.JumpRecovery < g.count {
if _, _, _, a := g.level.LevelImage.At(g.player.X-util.FrameWidth/2, g.player.Y-g.level.JumpHeight).RGBA(); a == 0 {
if _, _, _, a := g.level.LevelImage.At(g.player.X-sys.FrameWidth/2, g.player.Y-g.level.JumpHeight).RGBA(); a == 0 {
g.player.YVelocity = -float64(g.level.JumpHeight)
g.player.Y += int(g.player.YVelocity)
g.player.TimeSinceLastJump = g.count
Expand All @@ -77,23 +79,23 @@ func (g *Game) Update() error {
}

touchingTop := false
if _, _, _, a := g.level.LevelImage.At(g.player.X-util.FrameWidth/2, g.player.Y).RGBA(); a > 0 {
if _, _, _, a := g.level.LevelImage.At(g.player.X-sys.FrameWidth/2, g.player.Y).RGBA(); a > 0 {
touchingTop = true
}

// Running
// TODO allow WASD
if ebiten.IsKeyPressed(ebiten.KeyArrowRight) {
g.player.FacingLeft = false
if g.player.X < g.level.LevelImage.Bounds().Dx()-util.ScreenWidth/2+util.FrameWidth/2-1 && !touchingRight && !rightAdjacent {
if g.player.X < g.level.LevelImage.Bounds().Dx()-sys.ScreenWidth/2+sys.FrameWidth/2-1 && !touchingRight && !rightAdjacent {
g.player.Slides = &g.player.RunFrames
g.player.X += g.level.MoveSpeed
}
}

if ebiten.IsKeyPressed(ebiten.KeyArrowLeft) {
g.player.FacingLeft = true
if g.player.X > util.ScreenWidth/2+util.FrameWidth/2 && !touchingLeft && !leftAdjacent {
if g.player.X > sys.ScreenWidth/2+sys.FrameWidth/2 && !touchingLeft && !leftAdjacent {
g.player.Slides = &g.player.RunFrames
g.player.X -= g.level.MoveSpeed
}
Expand All @@ -106,10 +108,10 @@ func (g *Game) Update() error {
g.player.YVelocity = 0
}

if _, _, _, a := g.level.LevelImage.At(g.player.X-util.FrameWidth/2, g.player.Y+util.FrameHeight-1).RGBA(); a != 0 {
if _, _, _, a := g.level.LevelImage.At(g.player.X-sys.FrameWidth/2, g.player.Y+sys.FrameHeight-1).RGBA(); a != 0 {
for a != 0 {
g.player.Y -= 1
_, _, _, a = g.level.LevelImage.At(g.player.X-util.FrameWidth/2, g.player.Y+util.FrameHeight-1).RGBA()
_, _, _, a = g.level.LevelImage.At(g.player.X-sys.FrameWidth/2, g.player.Y+sys.FrameHeight-1).RGBA()
}
}

Expand All @@ -123,7 +125,7 @@ func (g *Game) Update() error {

// Pick up coins
for _, actor := range g.level.Actors {
if actor.Exists && actor.Kind == "c" && actor.X+util.FrameWidth/2 > g.player.X-util.FrameWidth && actor.X+util.FrameWidth/2 < g.player.X && actor.Y+util.FrameHeight/2 > g.player.Y && actor.Y+util.FrameHeight/2 < g.player.Y+util.FrameHeight {
if actor.Exists && actor.Kind == "c" && actor.X+sys.FrameWidth/2 > g.player.X-sys.FrameWidth && actor.X+sys.FrameWidth/2 < g.player.X && actor.Y+sys.FrameHeight/2 > g.player.Y && actor.Y+sys.FrameHeight/2 < g.player.Y+sys.FrameHeight {
actor.Exists = false
g.player.Coins++
// TODO noticeable framerate drop when sounds play
Expand All @@ -134,12 +136,12 @@ func (g *Game) Update() error {

// Fall in holes
// TODO make player lose money when falling in a hole
if g.player.Y > util.ScreenHeight*4 {
if g.player.Y > sys.ScreenHeight*4 {
spawnX, spawnY := 0, 0
for _, actor := range g.level.Actors {
if actor.Kind == "s" {
if actor.X > spawnX && actor.X < g.player.X {
spawnX = actor.X + util.FrameWidth
spawnX = actor.X + sys.FrameWidth
spawnY = actor.Y
}

Expand Down
36 changes: 18 additions & 18 deletions level/level.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import (
"strings"

"github.com/hajimehoshi/ebiten/v2"
"github.com/jcgraybill/it-costs-money/util"
"github.com/jcgraybill/it-costs-money/sys"
)

type Level struct {
Expand All @@ -25,26 +25,26 @@ type Actor struct {

func New(levelNumber int, tiles []*ebiten.Image) Level {
var l Level
l.CoinDecay = 120
l.CoinDecay = 90
l.MoveSpeed = 4
l.JumpHeight = 8
l.Gravity = 0.5
l.BgImage1 = util.LoadImage("assets/Background_Layer_1.png")
l.BgImage2 = util.LoadImage("assets/Background_Layer_2.png")
l.BgImage3 = util.LoadImage("assets/Background_Layer_3.png")
l.LevelImage = generateLevelImage(fmt.Sprintf("level/leveldata/level_%d_main.csv", levelNumber), tiles)
l.LevelBackgroundImage = generateLevelImage(fmt.Sprintf("level/leveldata/level_%d_background.csv", levelNumber), tiles)
l.LevelForegroundImage = generateLevelImage(fmt.Sprintf("level/leveldata/level_%d_foreground.csv", levelNumber), tiles)
l.BgImage1 = sys.LoadImage("assets/Background_Layer_1.png")
l.BgImage2 = sys.LoadImage("assets/Background_Layer_2.png")
l.BgImage3 = sys.LoadImage("assets/Background_Layer_3.png")
l.LevelImage = generateLevelImage(fmt.Sprintf("leveldata/level_%d_main.csv", levelNumber), tiles)
l.LevelBackgroundImage = generateLevelImage(fmt.Sprintf("leveldata/level_%d_background.csv", levelNumber), tiles)
l.LevelForegroundImage = generateLevelImage(fmt.Sprintf("leveldata/level_%d_foreground.csv", levelNumber), tiles)

l.Actors = loadActors(fmt.Sprintf("level/leveldata/level_%d_actors.csv", levelNumber))
l.Actors = loadActors(fmt.Sprintf("leveldata/level_%d_actors.csv", levelNumber))
return l
}

func generateLevelImage(path string, tiles []*ebiten.Image) *ebiten.Image {
levelData := make([][]int, util.ScreenHeight/util.FrameHeight)
levelData := make([][]int, sys.ScreenHeight/sys.FrameHeight)
levelWidth := 0

data, err := util.GameData(path)
data, err := sys.GameData(path)

if err == nil {
for row, line := range strings.Split(string(data), "\n") {
Expand All @@ -70,16 +70,16 @@ func generateLevelImage(path string, tiles []*ebiten.Image) *ebiten.Image {
levelWidth += 1
// This is a hardware limitation, will vary machine by machine.
// FIXME slice levels into smaller images so the level can be arbitrarily long
if levelWidth *= util.FrameWidth; levelWidth > 16320 {
if levelWidth *= sys.FrameWidth; levelWidth > 16320 {
levelWidth = 16320
}

levelImage := ebiten.NewImage(levelWidth, util.ScreenHeight)
levelImage := ebiten.NewImage(levelWidth, sys.ScreenHeight)
for row, line := range levelData {
for col, cell := range line {
if cell > 0 && cell < len(tiles) {
op := &ebiten.DrawImageOptions{}
op.GeoM.Translate(float64(col*util.FrameWidth), float64(row*util.FrameHeight))
op.GeoM.Translate(float64(col*sys.FrameWidth), float64(row*sys.FrameHeight))
levelImage.DrawImage(tiles[cell], op)
}
}
Expand All @@ -90,13 +90,13 @@ func generateLevelImage(path string, tiles []*ebiten.Image) *ebiten.Image {
func loadActors(path string) []*Actor {
actors := make([]*Actor, 0)

data, err := util.GameData(path)
data, err := sys.GameData(path)

if err == nil {
for row, line := range strings.Split(string(data), "\n") {
for col, cell := range strings.Split(line, ",") {
if cell != "0" && cell != "" {
actors = append(actors, &Actor{X: col * util.FrameWidth, Y: row * util.FrameHeight, Exists: true, Kind: cell})
actors = append(actors, &Actor{X: col * sys.FrameWidth, Y: row * sys.FrameHeight, Exists: true, Kind: cell})
}
}
}
Expand All @@ -111,10 +111,10 @@ func (l Level) StartPosition() (x, y int) {
for _, actor := range l.Actors {
if actor.Kind == "s" {
if x == 0 {
x = actor.X + util.FrameWidth
x = actor.X + sys.FrameWidth
y = actor.Y
} else if x > actor.X {
x = actor.X + util.FrameWidth
x = actor.X + sys.FrameWidth
y = actor.Y
}
}
Expand Down
11 changes: 7 additions & 4 deletions leveleditor.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,22 +9,23 @@ import (
"github.com/hajimehoshi/ebiten/v2"
"github.com/hajimehoshi/ebiten/v2/inpututil"
"github.com/jcgraybill/it-costs-money/level"
"github.com/jcgraybill/it-costs-money/util"
"github.com/jcgraybill/it-costs-money/sys"
)

func levelEditor(g *Game) string {
// Live reload of level
if inpututil.IsKeyJustPressed(ebiten.KeyR) {
g.level = level.New(0, g.tiles)
}

// skip ahead to next spawn point
if inpututil.IsKeyJustPressed(ebiten.KeyS) {
spawnX, spawnY := g.level.LevelImage.Bounds().Dx(), 0
foundSpawn := false
for _, actor := range g.level.Actors {
if actor.Kind == "s" {
if actor.X > g.player.X && actor.X < spawnX {
spawnX = actor.X + util.FrameWidth
spawnX = actor.X + sys.FrameWidth
spawnY = actor.Y
foundSpawn = true
}
Expand All @@ -39,11 +40,13 @@ func levelEditor(g *Game) string {
g.player.X, g.player.Y = g.level.StartPosition()
}
}

// display current coordinates of player
xCellRune := ' '
if xCell := (g.player.X-util.FrameWidth/2)/(util.FrameWidth*26) + 64; xCell > 64 {
if xCell := (g.player.X-sys.FrameWidth/2)/(sys.FrameWidth*26) + 64; xCell > 64 {
xCellRune = rune(xCell)
}
pos := fmt.Sprintf("%c%c:%d", xCellRune, rune(((g.player.X-util.FrameWidth/2)/util.FrameWidth)%26+65), g.player.Y/util.FrameWidth+1)
pos := fmt.Sprintf("%c%c:%d", xCellRune, rune(((g.player.X-sys.FrameWidth/2)/sys.FrameWidth)%26+65), g.player.Y/sys.FrameWidth+1)

return fmt.Sprintf("\n[%s](r)eload (s)pawn\ntps %d fps %d", pos, int(ebiten.CurrentTPS()), int(ebiten.CurrentFPS()))

Expand Down
Loading

0 comments on commit 6fd4923

Please sign in to comment.