diff options
| -rw-r--r-- | main.go | 19 | ||||
| -rw-r--r-- | objects.go | 198 | 
2 files changed, 210 insertions, 7 deletions
| @@ -18,10 +18,11 @@ const (      screenHeight = 240      tileSize = 16      playerSpeed = 2.1 -    jumpHeight = 3.2 +    jumpHeight = 4      rewindSpeed = 2      gravity = 0.16 -    friction = 0.9 +    friction = 0.75 +    airResistance = 0.98  )  var ( @@ -111,6 +112,8 @@ func (g *Game) Init() {      g.toPlace = append(g.toPlace, NewBox(0, 0))      g.toPlace = append(g.toPlace, NewBox(0, 0))      g.toPlace = append(g.toPlace, NewSpring(0, 0)) +    g.toPlace = append(g.toPlace, NewSpike(0, 0)) +    g.toPlace = append(g.toPlace, NewLeftSpike(0, 0))      g.surface = ebiten.NewImage(screenWidth, screenHeight)      g.shaderName = "none" @@ -162,9 +165,7 @@ func (g *Game) Update() error {          if g.state == REVERSING {              g.state = IN_GAME              g.shaderName = "none" -        } - -        if g.state == IN_GAME { +        } else if g.state == IN_GAME {              g.state = REVERSING              g.shaderName = "vcr"          } @@ -200,12 +201,16 @@ func (g *Game) Update() error {      if g.state == PLACING {          if len(g.toPlace) > 0 { +            placeable := g.toPlace[0]              cx, cy := ebiten.CursorPosition()              cx = int(math.Floor(float64(cx)/float64(g.tilemap.tileSize)))*g.tilemap.tileSize              cy = int(math.Floor(float64(cy)/float64(g.tilemap.tileSize)))*g.tilemap.tileSize -            g.toPlace[0].x = float32(cx) -            g.toPlace[0].y = float32(cy) +            cx += placeable.offsetX +            cy += placeable.offsetY + +            placeable.x = float32(cx) +            placeable.y = float32(cy)              if inpututil.IsMouseButtonJustPressed(ebiten.MouseButton0) {                  g.PlaceObject(cx, cy) diff --git a/objects.go b/objects.go new file mode 100644 index 0000000..9eb4167 --- /dev/null +++ b/objects.go @@ -0,0 +1,198 @@ +package main + +import ( +	"log" +    "image" +    "github.com/hajimehoshi/ebiten/v2" +	"github.com/hajimehoshi/ebiten/v2/ebitenutil" +) + +const ( +    SPRING_FORCE = 8 +) + +type GameObject struct { +    startx, starty float32 +    x, y float32 +    vx, vy float32 + +    offsetX, offsetY int + +    friction float32 +    resistance float32 +    image *ebiten.Image +    onGround bool +    onCollideX func(this, other *GameObject) bool +    onCollideY func(this, other *GameObject) bool +} + + +type Player struct { +    GameObject +} + +func (o * GameObject) Update(tilemap Tilemap, others []*GameObject) { +    o.vy += gravity + +    o.vx *= o.resistance +    o.vy *= o.resistance + +    o.x += o.vx +    if o.HasCollision(tilemap, others, true) { +        o.x -= o.vx +        o.vx = 0 +    } + +    o.y += o.vy +    if o.HasCollision(tilemap, others, false) { +        o.onGround = true; +        o.vx *= o.friction + +        o.y -= o.vy +        o.vy = 0 +    } else { +        o.onGround = false; +    } +} + +func (o * GameObject) HasCollision(tilemap Tilemap, others []*GameObject, x bool) bool { +    if tilemap.CollideObject(o) { +        return true +    } +    for _, obj := range others { +        if obj.Collide(o) { +            var f func(this, other *GameObject) bool +            if x { +                f = obj.onCollideX +            } else { +                f = obj.onCollideY +            } + +            if f == nil{ +                return true +            } +            return f(obj, o) +        } +    } +    return false +} + +func (o * GameObject) Draw(screen *ebiten.Image, tilemap Tilemap) { +    op := &ebiten.DrawImageOptions{} +    op.GeoM.Translate(float64(o.x), float64(o.y)) +    screen.DrawImage(o.image, op) +} + +func (object * GameObject) Collide(other *GameObject) bool { +    maxX1 := object.x + float32(object.image.Bounds().Dx()) +    maxY1 := object.y + float32(object.image.Bounds().Dy()) +    minX1 := object.x +    minY1 := object.y + +    maxX2 := other.x + float32(other.image.Bounds().Dx()) +    maxY2 := other.y + float32(other.image.Bounds().Dy()) +    minX2 := other.x +    minY2 := other.y + +    if (minX1 == minX2 && maxX1 == maxX2 && minY1 == minY2 && maxY1 == maxY2) { +        return false +    } + +    return ! ( minX2 >= maxX1 || maxX2 <= minX1 || minY2 >= maxY1 || maxY2 <= minY1) +} + +func (object * GameObject) ToRect() image.Rectangle { +    width := object.image.Bounds().Dx() +    height := object.image.Bounds().Dy() +    x := int(object.x) +    y := int(object.y) +    return image.Rect(x, y, x+width, y+height) +} + +func OnCollideGeneric(this, other *GameObject) bool { +    return true +} + +func NewObject(x, y float32) *GameObject{ +    obj := &GameObject{ +        startx: x, +        starty: y, +    } + +    obj.friction = friction +    obj.resistance = airResistance +    obj.x = obj.startx +    obj.y = obj.starty +    return obj +} + +func NewPlayer(x, y float32) *GameObject{ +    player := NewObject(x, y) + +    playerImage, _, err := ebitenutil.NewImageFromFile("Assets/Main Characters/Ninja Frog/Idle (32x32).png") +	if err != nil { +		log.Fatal(err) +	} + +    player.image = playerImage.SubImage(image.Rect(4, 8, 27, 32)).(*ebiten.Image) + +    return player +} + +func NewExit(x, y float32) *GameObject{ +    exit := NewObject(x, y) + +    exit.image = tilesImage.SubImage(image.Rect(0, 16, 32, 48)).(*ebiten.Image) + +    return exit +} + +func NewBox(x, y float32) *GameObject{ +    box := NewObject(x, y) + +    box.image = tilesImage.SubImage(image.Rect(160, 0, 176, 16)).(*ebiten.Image) + +    return box +} + +func NewSpring(x, y float32) *GameObject{ +    spring := NewObject(x, y) + +    spring.image = tilesImage.SubImage(image.Rect(176, 0, 192, 16)).(*ebiten.Image) +    spring.onCollideY = OnCollideSpring + +    return spring +} + +func NewSpike(x, y float32) *GameObject{ +    spike := NewObject(x, y) + +    spike.offsetY = 3 +    spike.image = tilesImage.SubImage(image.Rect(192, 3, 208, 16)).(*ebiten.Image) +    spike.onCollideY = OnCollideSpike + +    return spike +} + +func NewLeftSpike(x, y float32) *GameObject{ +    spike := NewObject(x, y) + +    spike.offsetX = 3 +    spike.image = tilesImage.SubImage(image.Rect(195, 16, 208, 32)).(*ebiten.Image) +    spike.onCollideX = OnCollideSpike + +    return spike +} + +func OnCollideSpring(this, other *GameObject) bool { +    other.vy -= SPRING_FORCE +    other.onGround = true +    return false +} + +func OnCollideSpike(this, other *GameObject) bool { +    other.x = other.startx +    other.y = other.starty +    return true +} + | 
