summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--main.go19
-rw-r--r--objects.go198
2 files changed, 210 insertions, 7 deletions
diff --git a/main.go b/main.go
index 7c4e014..fb86e10 100644
--- a/main.go
+++ b/main.go
@@ -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
+}
+