Improved ropes

This commit is contained in:
nefrace 2023-01-04 00:00:32 +03:00
parent 845a7d3aba
commit b360d93333
4 changed files with 135 additions and 24 deletions

13
main.go
View File

@ -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

View File

@ -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)
}
}
}
}

View File

@ -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)

View File

@ -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
}