summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordavidovski <david@davidovski.xyz>2023-10-18 03:58:03 +0100
committerdavidovski <david@davidovski.xyz>2023-10-18 03:58:03 +0100
commit8f71134f6114063189fbef4674c21ce1bba24b2a (patch)
treec46231f426ca97e3a674f8a49787861e4822a99e
parent4501207261be3b4685830feaa6d3a5b478c907cc (diff)
add scuffed physics
-rw-r--r--pengui.go152
1 files changed, 121 insertions, 31 deletions
diff --git a/pengui.go b/pengui.go
index 79c8571..afc7843 100644
--- a/pengui.go
+++ b/pengui.go
@@ -11,6 +11,10 @@ import (
"github.com/hajimehoshi/ebiten/v2/vector"
)
+const GROUND_RESISTANCE = 0.8
+const AIR_RESISTANCE = 0.99
+var red = color.RGBA{0xcc, 0x66, 0x66, 0xff}
+var green = color.RGBA{0xb5, 0xbd, 0x68, 0xff}
const screen_w, screen_h = 640, 480
type Penguin struct {
@@ -18,6 +22,7 @@ type Penguin struct {
x, y float64
xv, yv float64
+ onGround bool
}
func newPenguin() Penguin {
@@ -37,34 +42,92 @@ func newPenguin() Penguin {
return penguin;
}
-func (penguin *Penguin) draw(screen *ebiten.Image) {
+func (p *Penguin) Width() (float64) {
+ return float64(p.img.Bounds().Dx())
+}
+
+func (p *Penguin) Height() (float64) {
+ return float64(p.img.Bounds().Dy())
+}
+
+func (p *Penguin) Cx() (float64) {
+ return p.x + float64(p.img.Bounds().Dx()) / 2
+}
+
+func (p *Penguin) Cy() (float64) {
+ return p.y + float64(p.img.Bounds().Dy()) / 2
+}
+
+func (penguin *Penguin) draw(screen *ebiten.Image, game Game) {
op := &ebiten.DrawImageOptions{}
- op.GeoM.Translate(penguin.x, penguin.y)
+
+ if penguin.onGround {
+ angle := game.ground.angle(penguin.Cx(), 2)
+ tx, ty := float64(penguin.Width()) / 2, float64(penguin.Height())
+
+ op.GeoM.Translate(-tx, -ty)
+ op.GeoM.Rotate(angle)
+ op.GeoM.Translate(tx, ty)
+ }
+
+ op.GeoM.Translate(penguin.x, penguin.y)
screen.DrawImage(penguin.img, op)
}
-func (penguin *Penguin) drawBounds(screen *ebiten.Image) {
+func (penguin *Penguin) drawBounds(screen *ebiten.Image, game Game) {
+
+ var m float64 = 16
+
+ vector.StrokeLine(screen,
+ float32(penguin.Cx()), float32(penguin.y+penguin.Height()),
+ float32(penguin.Cx() + penguin.xv*m), float32(penguin.y + penguin.Height() + penguin.yv*m),
+ 4, red, true)
+
+ if penguin.onGround{
+ fx, fy := Normalize(game.ground.normal(game.penguin.Cx(), 2))
+ vector.StrokeLine(screen,
+ float32(penguin.Cx()), float32(penguin.y+penguin.Height()),
+ float32(penguin.Cx() + fx*penguin.Height()), float32(penguin.y + penguin.Height() + fy*penguin.Height()),
+ 4, green, true)
+ return
+ }
+
vector.StrokeRect(screen,
float32(penguin.x), float32(penguin.y),
- float32(penguin.img.Bounds().Dx()), float32(penguin.img.Bounds().Dy()),
- 4, color.RGBA{0xcc, 0x66, 0x66, 0xff}, true)
+ float32(penguin.Width()), float32(penguin.Height()),
+ 4, red, true)
+
+
}
func (penguin *Penguin) update(g *Game) {
- if penguin.collideWithCurve(g.ground, penguin.xv, 0){
- penguin.xv = 0
- penguin.yv -= 4
- } else {
+ if penguin.onGround{
+ penguin.yv = 0
+ penguin.y = g.ground(penguin.Cx()) - float64(penguin.img.Bounds().Dy())
penguin.x += penguin.xv
- penguin.xv *= 0.9
+ penguin.y += penguin.yv
+
+ dx, dy := Normalize(g.ground.normal(penguin.x, 1))
+ penguin.xv += math.Sqrt(dx*dx + dy*dy) * math.Sin(g.ground.angle(penguin.Cx(), 2)) * 4
+ //penguin.yv += math.Sqrt(dx*dx + dy*dy) * math.Cos(g.ground.angle(penguin.Cx(), 2)) * 4
+ penguin.xv *= GROUND_RESISTANCE
+
+ return
}
+ penguin.yv += 0.9
+
+ penguin.x += penguin.xv
+ penguin.y += penguin.yv
+
+ penguin.xv *= AIR_RESISTANCE
+ penguin.yv *= AIR_RESISTANCE
+
if penguin.collideWithCurve(g.ground, 0, penguin.yv){
penguin.yv = 0
- } else {
- penguin.y += penguin.yv
- penguin.yv += 0.9
- }
+ penguin.onGround = true
+ return
+ }
}
func (p *Penguin) collideWithCurve(curve Curve, xv, yv float64) bool {
@@ -100,26 +163,51 @@ func (curve Curve) draw(dst *ebiten.Image, clr color.Color, width float32, resol
}
}
+func (curve Curve) delta(x, r float64) (float64, float64){
+ x1, x2 := x + r, x - r
+ y1, y2 := curve(x1), curve(x2)
+ dx, dy := x2 - x1, y2 - y1
+ return dx, dy
+}
+
+func (curve Curve) angle(x, r float64) (float64){
+ dx, dy := curve.delta(x, r)
+ return math.Atan(dy / dx)
+}
+
+func (curve Curve) normal(x, r float64) (float64, float64){
+ dx, dy := curve.delta(x, r)
+ //m := -(dx / dy)
+ return -dy,dx
+}
+
+func Normalize(x, y float64) (float64, float64) {
+ m := math.Sqrt(x*x + y*y)
+ return x/m, y/m
+}
+
type Game struct{
penguin Penguin
ground Curve
}
func (g *Game) Update() error {
- if ebiten.IsKeyPressed(ebiten.KeyArrowRight) {
- g.penguin.xv = 4
- }
-
- if ebiten.IsKeyPressed(ebiten.KeyArrowLeft) {
- g.penguin.xv = -4
- }
-
- if ebiten.IsKeyPressed(ebiten.KeyArrowUp) {
- g.penguin.yv = -4
- }
-
- if ebiten.IsKeyPressed(ebiten.KeyArrowDown) {
- g.penguin.yv = 4
+ if g.penguin.onGround{
+ if ebiten.IsKeyPressed(ebiten.KeyA) {
+ g.penguin.xv = -4
+ }
+
+ if ebiten.IsKeyPressed(ebiten.KeyD) {
+ g.penguin.xv = 4
+ }
+
+ if ebiten.IsKeyPressed(ebiten.KeySpace) {
+ g.penguin.onGround = false
+ fx, fy := Normalize(g.ground.normal(g.penguin.Cx(), 2))
+ const jumpHeight = 8
+ g.penguin.xv += fx * jumpHeight
+ g.penguin.yv += fy * jumpHeight
+ }
}
g.penguin.update(g)
@@ -131,8 +219,8 @@ func (g *Game) Draw(screen *ebiten.Image) {
screen.Fill(color.RGBA{0xfe, 0xfe, 0xfe, 0xff})
g.ground.draw(screen, color.RGBA{0x19, 0x19, 0x19, 0xff}, 4, 16, true);
- g.penguin.draw(screen)
- g.penguin.drawBounds(screen)
+ g.penguin.draw(screen, *g)
+ g.penguin.drawBounds(screen, *g)
}
func (g *Game) Layout(outsideWidth, outsideHeight int) (screenWidth, screenHeight int) {
@@ -146,7 +234,9 @@ func main() {
game := Game{}
game.ground = func(x float64)(y float64) {
- return 200-math.Pow((x - 320)/320, 3)+math.Pow((x-320), 2)/300
+ //return 200-math.Pow((x - 320)/320, 3)+math.Pow((x-320), 2)/300
+ //return 400
+ return 400+50*math.Sin(x/50)
}
game.init()