From b360d93333b24cd356ba916ced4812eff6b4b3e4 Mon Sep 17 00:00:00 2001 From: nefrace Date: Wed, 4 Jan 2023 00:00:32 +0300 Subject: [PATCH] Improved ropes --- main.go | 13 ++++----- player.go | 78 +++++++++++++++++++++++++++++++++++++++++++----------- ropes.go | 47 ++++++++++++++++++++++++++++++-- vectors.go | 21 +++++++++++++++ 4 files changed, 135 insertions(+), 24 deletions(-) diff --git a/main.go b/main.go index 7f3f116..52b12c3 100644 --- a/main.go +++ b/main.go @@ -32,20 +32,21 @@ func start() { w4.PALETTE[1] = 0x012824 w4.PALETTE[2] = 0x265935 w4.PALETTE[3] = 0xff4d6d - player = &Player{ - Position: Vector{80, 80}, - Speed: Vector{}, - Gamepad: w4.GAMEPAD1, - } for i := 0; i < 4; i++ { p, s := CreateRope( Vector{0, rand.Float64()*40 + float64(i*40)}, Vector{160, rand.Float64()*40 + float64(i*40)}, - 15, + 10, ) points = append(points, p...) sticks = append(sticks, s...) } + player = &Player{ + Position: Vector{80, 80}, + Speed: Vector{}, + Gamepad: w4.GAMEPAD1, + StickGrabbed: sticks[rand.Intn(len(sticks)-1)], + } } //go:export update diff --git a/player.go b/player.go index 7e1ecac..8b9ff0d 100644 --- a/player.go +++ b/player.go @@ -1,13 +1,17 @@ package main -import "cart/w4" +import ( + "cart/w4" + "math" +) type Player struct { - Position Vector - Speed Vector - PointGrabbed *Point + Position Vector + Speed Vector + //PointGrabbed *Point + StickGrabbed *Stick + StickOffset float64 GrabTimeout uint - Offset float64 Gamepad *uint8 } @@ -23,32 +27,74 @@ func (p *Player) Update() { p.Speed.X += 1 } isJumping := *p.Gamepad&w4.BUTTON_DOWN == 0 - p.Speed.Y += gravity - if p.PointGrabbed != nil { + p.Speed.Y = math.Min(4, p.Speed.Y+gravity) + if p.StickGrabbed != nil { p.Speed.Y = 0 - p.Position = p.PointGrabbed.Position + // p.Position = p.PointGrabbed.Position + if *p.Gamepad&w4.BUTTON_LEFT != 0 { + p.StickOffset -= 0.1 + } + if *p.Gamepad&w4.BUTTON_RIGHT != 0 { + p.StickOffset += 0.1 + } + if p.StickOffset < 0 { + point := p.StickGrabbed.PointA + if len(point.Sticks) == 1 { + p.StickOffset = 0 + } else { + p.StickGrabbed = point.Sticks[0] + p.StickOffset += 1 + } + } + if p.StickOffset > 1 { + point := p.StickGrabbed.PointB + if len(point.Sticks) == 1 { + p.StickOffset = 1 + } else { + p.StickGrabbed = point.Sticks[1] + p.StickOffset -= 1 + } + } + p.Position = p.StickGrabbed.GetPosition(p.StickOffset) if *p.Gamepad&w4.BUTTON_2 != 0 { p.GrabTimeout = 10 if isJumping { p.GrabTimeout = 5 p.Speed.Y = -4.5 + impulse := p.Speed.MulScalar(-1) + p.StickGrabbed.PointA.Position.MoveVec(impulse) + p.StickGrabbed.PointB.Position.MoveVec(impulse) } - p.PointGrabbed = nil + p.StickGrabbed = nil } } else { p.Position.Move(p.Speed.X, p.Speed.Y) if *p.Gamepad&w4.BUTTON_DOWN == 0 && p.GrabTimeout == 0 { + distance := math.MaxFloat64 + var selectedPoint *Point for _, point := range points { diff := p.Position.Sub(point.Position) - if diff.LenSquared() < 25 { - // nearPoints = append(nearPoints, p) - *w4.DRAW_COLORS = 0x44 - w4.Rect(int(point.Position.X), int(point.Position.Y), 3, 3) - p.PointGrabbed = point - point.PreviousPosition.Move(-p.Speed.X*2, -p.Speed.Y*2) - break + dSquared := diff.LenSquared() + if dSquared < distance { + distance = dSquared + selectedPoint = point } } + stickDistance := math.MaxFloat64 + var selectedStick *Stick + for _, stick := range selectedPoint.Sticks { + distance := stick.GetDistance(p.Position) + if distance < stickDistance { + stickDistance = distance + selectedStick = stick + } + } + if stickDistance < 4 { + p.StickGrabbed = selectedStick + p.StickOffset = selectedStick.GetOffset(p.Position) + p.StickGrabbed.PointA.Position.MoveVec(p.Speed) + p.StickGrabbed.PointB.Position.MoveVec(p.Speed) + } } } } diff --git a/ropes.go b/ropes.go index 5d12ce1..9a94fd3 100644 --- a/ropes.go +++ b/ropes.go @@ -3,7 +3,6 @@ package main import ( "cart/w4" "math" - "strconv" ) type Point struct { @@ -11,6 +10,16 @@ type Point struct { PreviousPosition Vector IsLocked bool TimeOffset uint64 + Sticks []*Stick +} + +func (p *Point) AddStick(stick *Stick) *Point { + p.Sticks = append(p.Sticks, stick) + return p +} + +func (p *Point) GetMotion() Vector { + return p.Position.Sub(p.PreviousPosition) } func (p *Point) Draw() { @@ -31,6 +40,39 @@ type Stick struct { Length float64 } +func (s *Stick) GetVector() Vector { + return s.PointB.Position.Sub(s.PointA.Position) +} + +func (s *Stick) GetDistance(point Vector) float64 { + ab := s.GetVector() + ap := point.Sub(s.PointA.Position) + bp := point.Sub(s.PointB.Position) + + abbp := (ab.X*bp.X + ab.Y*bp.Y) + abap := (ab.X*ap.X + ab.Y*ap.Y) + + if abbp > 0 { + return bp.Len() + } else if abap < 0 { + return ap.Len() + } + mod := ab.Len() + return math.Abs(ab.X*ap.Y-ab.Y*ab.X) / mod +} + +func (s *Stick) GetPosition(offset float64) Vector { + diff := s.GetVector() + return s.PointA.Position.Sum(diff.MulScalar(offset)) +} + +func (s *Stick) GetOffset(p Vector) float64 { + ab := s.GetVector() + ap := p.Sub(s.PointA.Position) + projection := ap.ProjectTo(ab) + return projection.Len() / ab.Len() +} + func (s *Stick) Draw() { *w4.DRAW_COLORS = 0x3 w4.Line(int(s.PointA.Position.X), int(s.PointA.Position.Y), @@ -90,12 +132,13 @@ func CreateRope(start Vector, end Vector, divisions int) ([]*Point, []*Stick) { diffX := pos.X - lastPoint.Position.X diffY := pos.Y - lastPoint.Position.Y len := math.Sqrt(diffX*diffX + diffY*diffY) - w4.Trace("Length between points is " + strconv.FormatFloat(len, 'f', 3, 64)) stick := Stick{ PointA: lastPoint, PointB: &point, Length: len, } + stick.PointA.AddStick(&stick) + stick.PointB.AddStick(&stick) sticks = append(sticks, &stick) } points = append(points, &point) diff --git a/vectors.go b/vectors.go index 81c9006..1f1d728 100644 --- a/vectors.go +++ b/vectors.go @@ -10,6 +10,13 @@ type Vector struct { Y float64 } +func Vec(x float64, y float64) Vector { + return Vector{ + x, + y, + } +} + func (v *Vector) String() string { return "(" + strconv.FormatFloat(v.X, 'f', 3, 64) + "; " + strconv.FormatFloat(v.Y, 'f', 3, 64) + ")" } @@ -57,7 +64,21 @@ func (v *Vector) Normalized() Vector { return Vector{x, y} } +func (v *Vector) Dot(v2 Vector) float64 { + return v.X*v2.X + v.Y*v2.Y +} + +func (v *Vector) ProjectTo(v2 Vector) Vector { + abdot := v.Dot(v2) + bbdot := v2.Dot(v2) + return v2.MulScalar(abdot / bbdot) +} + func (v *Vector) Move(x float64, y float64) { v.X += x v.Y += y } +func (v *Vector) MoveVec(v2 Vector) { + v.X += v2.X + v.Y += v2.Y +}